• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 15263807472

26 May 2025 08:53PM UTC coverage: 72.046% (-0.002%) from 72.048%
15263807472

push

github

yuwata
src/core/manager.c: log preset activity on first boot

This gives us a little more information about what units were enabled
or disabled on that first boot and will be useful for OS developers
tracking down the source of unit state.

An example with this enabled looks like:

```
NET: Registered PF_VSOCK protocol family
systemd[1]: Applying preset policy.
systemd[1]: Unit /etc/systemd/system/dnsmasq.service is masked, ignoring.
systemd[1]: Unit /etc/systemd/system/systemd-repart.service is masked, ignoring.
systemd[1]: Removed '/etc/systemd/system/sockets.target.wants/systemd-resolved-monitor.socket'.
systemd[1]: Removed '/etc/systemd/system/sockets.target.wants/systemd-resolved-varlink.socket'.
systemd[1]: Created symlink '/etc/systemd/system/multi-user.target.wants/var-mnt-workdir.mount' → '/etc/systemd/system/var-mnt-workdir.mount'.
systemd[1]: Created symlink '/etc/systemd/system/multi-user.target.wants/var-mnt-workdir\x2dtmp.mount' → '/etc/systemd/system/var-mnt-workdir\x2dtmp.mount'.
systemd[1]: Created symlink '/etc/systemd/system/afterburn-sshkeys.target.requires/afterburn-sshkeys@core.service' → '/usr/lib/systemd/system/afterburn-sshkeys@.service'.
systemd[1]: Created symlink '/etc/systemd/system/sockets.target.wants/systemd-resolved-varlink.socket' → '/usr/lib/systemd/system/systemd-resolved-varlink.socket'.
systemd[1]: Created symlink '/etc/systemd/system/sockets.target.wants/systemd-resolved-monitor.socket' → '/usr/lib/systemd/system/systemd-resolved-monitor.socket'.
systemd[1]: Populated /etc with preset unit settings.
```

Considering it only happens on first boot and not on every boot I think
the extra information is worth the extra verbosity in the logs just for
that boot.

5 of 6 new or added lines in 1 file covered. (83.33%)

5463 existing lines in 165 files now uncovered.

299151 of 415222 relevant lines covered (72.05%)

702386.45 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

55.05
/src/basic/random-util.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <elf.h>
4
#include <fcntl.h>
5
#include <linux/random.h>
6
#include <string.h>
7
#include <sys/auxv.h>
8
#include <sys/ioctl.h>
9
#include <threads.h>
10

11
#include "alloc-util.h"
12
#include "fd-util.h"
13
#include "fileio.h"
14
#include "io-util.h"
15
#include "iovec-util.h"
16
#include "log.h"
17
#include "missing_random.h"
18
#include "parse-util.h"
19
#include "pidfd-util.h"
20
#include "process-util.h"
21
#include "random-util.h"
22
#include "sha256.h"
23
#include "time-util.h"
24

25
/* This is a "best effort" kind of thing, but has no real security value. So, this should only be used by
26
 * random_bytes(), which is not meant for crypto. This could be made better, but we're *not* trying to roll a
27
 * userspace prng here, or even have forward secrecy, but rather just do the shortest thing that is at least
28
 * better than libc rand(). */
UNCOV
29
static void fallback_random_bytes(void *p, size_t n) {
×
UNCOV
30
        static thread_local uint64_t fallback_counter = 0;
×
UNCOV
31
        struct {
×
32
                char label[32];
33
                uint64_t call_id, block_id;
34
                usec_t stamp_mono, stamp_real;
35
                pid_t pid, tid;
36
                uint64_t pidfdid;
37
                uint8_t auxval[16];
38
        } state = {
×
39
                /* Arbitrary domain separation to prevent other usage of AT_RANDOM from clashing. */
UNCOV
40
                .call_id = fallback_counter++,
×
UNCOV
41
                .stamp_mono = now(CLOCK_MONOTONIC),
×
UNCOV
42
                .stamp_real = now(CLOCK_REALTIME),
×
UNCOV
43
                .pid = getpid_cached(),
×
UNCOV
44
                .tid = gettid(),
×
45
        };
46

UNCOV
47
        memcpy(state.label, "systemd fallback random bytes v1", sizeof(state.label));
×
48
        memcpy(state.auxval, ULONG_TO_PTR(getauxval(AT_RANDOM)), sizeof(state.auxval));
×
49
        (void) pidfd_get_inode_id_self_cached(&state.pidfdid);
×
50

51
        while (n > 0) {
×
52
                struct sha256_ctx ctx;
×
53

UNCOV
54
                sha256_init_ctx(&ctx);
×
55
                sha256_process_bytes(&state, sizeof(state), &ctx);
×
56
                if (n < SHA256_DIGEST_SIZE) {
×
57
                        uint8_t partial[SHA256_DIGEST_SIZE];
×
UNCOV
58
                        sha256_finish_ctx(&ctx, partial);
×
59
                        memcpy(p, partial, n);
×
60
                        break;
×
61
                }
62
                sha256_finish_ctx(&ctx, p);
×
63
                p = (uint8_t *) p + SHA256_DIGEST_SIZE;
×
64
                n -= SHA256_DIGEST_SIZE;
×
65
                ++state.block_id;
×
66
        }
67
}
×
68

69
void random_bytes(void *p, size_t n) {
5,286,211✔
70
        static bool have_grndinsecure = true;
5,286,211✔
71

72
        assert(p || n == 0);
5,286,211✔
73

74
        if (n == 0)
5,286,211✔
75
                return;
76

77
        for (;;) {
5,286,211✔
78
                ssize_t l;
5,286,211✔
79

80
                l = getrandom(p, n, have_grndinsecure ? GRND_INSECURE : GRND_NONBLOCK);
5,286,211✔
81
                if (l < 0 && errno == EINVAL && have_grndinsecure) {
5,286,211✔
82
                        /* No GRND_INSECURE; fallback to GRND_NONBLOCK. */
UNCOV
83
                        have_grndinsecure = false;
×
UNCOV
84
                        continue;
×
85
                }
86
                if (l <= 0)
5,286,211✔
87
                        break; /* Will block (with GRND_NONBLOCK), or unexpected error. Give up and fallback
88
                                  to /dev/urandom. */
89

90
                if ((size_t) l == n)
5,286,211✔
91
                        return; /* Done reading, success. */
92

UNCOV
93
                p = (uint8_t *) p + l;
×
UNCOV
94
                n -= l;
×
95
                /* Interrupted by a signal; keep going. */
96
        }
97

98
        _cleanup_close_ int fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
5,286,211✔
UNCOV
99
        if (fd >= 0 && loop_read_exact(fd, p, n, false) >= 0)
×
UNCOV
100
                return;
×
101

102
        /* This is a terrible fallback. Oh well. */
UNCOV
103
        fallback_random_bytes(p, n);
×
104
}
105

106
int crypto_random_bytes(void *p, size_t n) {
140✔
107
        assert(p || n == 0);
140✔
108

109
        if (n == 0)
140✔
110
                return 0;
111

112
        for (;;) {
140✔
113
                ssize_t l;
140✔
114

115
                l = getrandom(p, n, 0);
140✔
116
                if (l < 0)
140✔
UNCOV
117
                        return -errno;
×
118
                if (l == 0)
140✔
119
                        return -EIO; /* Weird, should never happen. */
120

121
                if ((size_t) l == n)
140✔
122
                        return 0; /* Done reading, success. */
123

UNCOV
124
                p = (uint8_t *) p + l;
×
125
                n -= l;
×
126
                /* Interrupted by a signal; keep going. */
127
        }
128
}
129

130
int crypto_random_bytes_allocate_iovec(size_t n, struct iovec *ret) {
56✔
131
        _cleanup_free_ void *p = NULL;
56✔
132
        int r;
56✔
133

134
        assert(ret);
56✔
135

136
        p = malloc(MAX(n, 1U));
56✔
137
        if (!p)
56✔
138
                return -ENOMEM;
139

140
        r = crypto_random_bytes(p, n);
56✔
141
        if (r < 0)
56✔
142
                return r;
143

144
        *ret = IOVEC_MAKE(TAKE_PTR(p), n);
56✔
145
        return 0;
56✔
146
}
147

148
size_t random_pool_size(void) {
130✔
149
        _cleanup_free_ char *s = NULL;
130✔
150
        int r;
130✔
151

152
        /* Read pool size, if possible */
153
        r = read_one_line_file("/proc/sys/kernel/random/poolsize", &s);
130✔
154
        if (r < 0)
130✔
155
                log_debug_errno(r, "Failed to read pool size from kernel: %m");
130✔
156
        else {
157
                unsigned sz;
130✔
158

159
                r = safe_atou(s, &sz);
130✔
160
                if (r < 0)
130✔
UNCOV
161
                        log_debug_errno(r, "Failed to parse pool size: %s", s);
×
162
                else
163
                        /* poolsize is in bits on 2.6, but we want bytes */
164
                        return CLAMP(sz / 8, RANDOM_POOL_SIZE_MIN, RANDOM_POOL_SIZE_MAX);
130✔
165
        }
166

167
        /* Use the minimum as default, if we can't retrieve the correct value */
168
        return RANDOM_POOL_SIZE_MIN;
169
}
170

171
int random_write_entropy(int fd, const void *seed, size_t size, bool credit) {
73✔
172
        _cleanup_close_ int opened_fd = -EBADF;
73✔
173
        int r;
73✔
174

175
        assert(seed || size == 0);
73✔
176

177
        if (size == 0)
73✔
178
                return 0;
179

180
        if (fd < 0) {
73✔
181
                opened_fd = open("/dev/urandom", O_WRONLY|O_CLOEXEC|O_NOCTTY);
10✔
182
                if (opened_fd < 0)
10✔
UNCOV
183
                        return -errno;
×
184

185
                fd = opened_fd;
186
        }
187

188
        if (credit) {
73✔
UNCOV
189
                _cleanup_free_ struct rand_pool_info *info = NULL;
×
190

191
                /* The kernel API only accepts "int" as entropy count (which is in bits), let's avoid any
192
                 * chance for confusion here. */
UNCOV
193
                if (size > INT_MAX / 8)
×
194
                        return -EOVERFLOW;
195

UNCOV
196
                info = malloc(offsetof(struct rand_pool_info, buf) + size);
×
197
                if (!info)
×
198
                        return -ENOMEM;
199

UNCOV
200
                info->entropy_count = size * 8;
×
201
                info->buf_size = size;
×
UNCOV
202
                memcpy(info->buf, seed, size);
×
203

204
                if (ioctl(fd, RNDADDENTROPY, info) < 0)
×
205
                        return -errno;
×
206
        } else {
207
                r = loop_write(fd, seed, size);
73✔
208
                if (r < 0)
73✔
209
                        return r;
×
210
        }
211

212
        return 1;
213
}
214

215
uint64_t random_u64_range(uint64_t m) {
2,815,376✔
216
        uint64_t x, remainder;
2,815,376✔
217

218
        /* Generates a random number in the range 0…m-1, unbiased. (Java's algorithm) */
219

220
        if (m == 0) /* Let's take m == 0 as special case to return an integer from the full range */
2,815,376✔
UNCOV
221
                return random_u64();
×
222
        if (m == 1)
2,815,376✔
223
                return 0;
224

225
        remainder = UINT64_MAX % m;
2,715,376✔
226

227
        do {
2,715,376✔
228
                x = random_u64();
2,715,376✔
229
        } while (x >= UINT64_MAX - remainder);
2,715,376✔
230

231
        return x % m;
2,715,376✔
232
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc