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

systemd / systemd / 15986406979

30 Jun 2025 05:03PM UTC coverage: 72.045% (-0.09%) from 72.13%
15986406979

push

github

bluca
man/systemd-sysext: list ephemeral/ephemeral-import in the list of options

ephemeral/ephemeral-import are described as possible '--mutable' options but
not present in the list. Note, "systemd-sysext --help" lists them correctly.

300514 of 417119 relevant lines covered (72.05%)

708586.28 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
#include <unistd.h>
11

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

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

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

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

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

70
void random_bytes(void *p, size_t n) {
5,304,119✔
71
        static bool have_grndinsecure = true;
5,304,119✔
72

73
        assert(p || n == 0);
5,304,119✔
74

75
        if (n == 0)
5,304,119✔
76
                return;
77

78
        for (;;) {
5,304,119✔
79
                ssize_t l;
5,304,119✔
80

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

91
                if ((size_t) l == n)
5,304,119✔
92
                        return; /* Done reading, success. */
93

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

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

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

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

110
        if (n == 0)
139✔
111
                return 0;
112

113
        for (;;) {
139✔
114
                ssize_t l;
139✔
115

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

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

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

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

135
        assert(ret);
55✔
136

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

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

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

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

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

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

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

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

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

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

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

186
                fd = opened_fd;
187
        }
188

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

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

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

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

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

213
        return 1;
214
}
215

216
uint64_t random_u64_range(uint64_t m) {
2,815,401✔
217
        uint64_t x, remainder;
2,815,401✔
218

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

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

226
        remainder = UINT64_MAX % m;
2,715,401✔
227

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

232
        return x % m;
2,715,401✔
233
}
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