Bug Summary

File:build-scan/../src/random-seed/random-seed.c
Warning:line 60, column 17
Potential leak of memory pointed to by 'buf'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name random-seed.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I systemd-random-seed.p -I . -I .. -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/udev -I ../src/udev -I src/libudev -I ../src/libudev -I src/core -I ../src/core -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/random-seed/random-seed.c
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <errno(*__errno_location ()).h>
4#include <fcntl.h>
5#include <string.h>
6#include <sys/stat.h>
7#include <unistd.h>
8
9#include "alloc-util.h"
10#include "fd-util.h"
11#include "io-util.h"
12#include "log.h"
13#include "mkdir.h"
14#include "string-util.h"
15#include "util.h"
16
17#define POOL_SIZE_MIN1024 1024
18
19int main(int argc, char *argv[]) {
20 _cleanup_close___attribute__((cleanup(closep))) int seed_fd = -1, random_fd = -1;
21 _cleanup_free___attribute__((cleanup(freep))) void* buf = NULL((void*)0);
22 size_t buf_size = 0;
23 ssize_t k;
24 int r, open_rw_error;
25 FILE *f;
26 bool_Bool refresh_seed_file = true1;
27
28 if (argc != 2) {
1
Assuming 'argc' is equal to 2
2
Taking false branch
29 log_error("This program requires one argument.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/random-seed/random-seed.c", 29, __func__, "This program requires one argument."
) : -abs(_e); })
;
30 return EXIT_FAILURE1;
31 }
32
33 log_set_target(LOG_TARGET_AUTO);
34 log_parse_environment()log_parse_environment_realm(LOG_REALM_SYSTEMD);
35 log_open();
36
37 umask(0022);
38
39 /* Read pool size, if possible */
40 f = fopen("/proc/sys/kernel/random/poolsize", "re");
41 if (f) {
3
Assuming 'f' is null
4
Taking false branch
42 if (fscanf(f, "%zu", &buf_size) > 0)
43 /* poolsize is in bits on 2.6, but we want bytes */
44 buf_size /= 8;
45
46 fclose(f);
47 }
48
49 if (buf_size
4.1
'buf_size' is <= POOL_SIZE_MIN
<= POOL_SIZE_MIN1024)
5
Taking true branch
50 buf_size = POOL_SIZE_MIN1024;
51
52 buf = malloc(buf_size);
6
Memory is allocated
53 if (!buf) {
7
Assuming 'buf' is non-null
8
Taking false branch
54 r = log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/random-seed/random-seed.c"
, 54, __func__)
;
55 goto finish;
56 }
57
58 r = mkdir_parents_label(RANDOM_SEED"/var/lib/systemd/random-seed", 0755);
59 if (r < 0) {
9
Assuming 'r' is < 0
10
Taking true branch
60 log_error_errno(r, "Failed to create directory " RANDOM_SEED_DIR ": %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/random-seed/random-seed.c", 60, __func__, "Failed to create directory "
"/var/lib/systemd" ": %m") : -abs(_e); })
;
11
Potential leak of memory pointed to by 'buf'
61 goto finish;
62 }
63
64 /* When we load the seed we read it and write it to the device
65 * and then immediately update the saved seed with new data,
66 * to make sure the next boot gets seeded differently. */
67
68 if (streq(argv[1], "load")(strcmp((argv[1]),("load")) == 0)) {
69
70 seed_fd = open(RANDOM_SEED"/var/lib/systemd/random-seed", O_RDWR02|O_CLOEXEC02000000|O_NOCTTY0400|O_CREAT0100, 0600);
71 open_rw_error = -errno(*__errno_location ());
72 if (seed_fd < 0) {
73 refresh_seed_file = false0;
74
75 seed_fd = open(RANDOM_SEED"/var/lib/systemd/random-seed", O_RDONLY00|O_CLOEXEC02000000|O_NOCTTY0400);
76 if (seed_fd < 0) {
77 bool_Bool missing = errno(*__errno_location ()) == ENOENT2;
78
79 log_full_errno(missing ? LOG_DEBUG : LOG_ERR,({ int _level = ((missing ? 7 : 3)), _e = ((open_rw_error)), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/random-seed/random-seed.c", 80, __func__
, "Failed to open " "/var/lib/systemd/random-seed" " for writing: %m"
) : -abs(_e); })
80 open_rw_error, "Failed to open " RANDOM_SEED " for writing: %m")({ int _level = ((missing ? 7 : 3)), _e = ((open_rw_error)), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/random-seed/random-seed.c", 80, __func__
, "Failed to open " "/var/lib/systemd/random-seed" " for writing: %m"
) : -abs(_e); })
;
81 r = log_full_errno(missing ? LOG_DEBUG : LOG_ERR,({ int _level = ((missing ? 7 : 3)), _e = (((*__errno_location
()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm
(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((
_realm) << 10 | (_level)), _e, "../src/random-seed/random-seed.c"
, 82, __func__, "Failed to open " "/var/lib/systemd/random-seed"
" for reading: %m") : -abs(_e); })
82 errno, "Failed to open " RANDOM_SEED " for reading: %m")({ int _level = ((missing ? 7 : 3)), _e = (((*__errno_location
()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm
(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((
_realm) << 10 | (_level)), _e, "../src/random-seed/random-seed.c"
, 82, __func__, "Failed to open " "/var/lib/systemd/random-seed"
" for reading: %m") : -abs(_e); })
;
83 if (missing)
84 r = 0;
85
86 goto finish;
87 }
88 }
89
90 random_fd = open("/dev/urandom", O_RDWR02|O_CLOEXEC02000000|O_NOCTTY0400, 0600);
91 if (random_fd < 0) {
92 random_fd = open("/dev/urandom", O_WRONLY01|O_CLOEXEC02000000|O_NOCTTY0400, 0600);
93 if (random_fd < 0) {
94 r = log_error_errno(errno, "Failed to open /dev/urandom: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/random-seed/random-seed.c", 94, __func__
, "Failed to open /dev/urandom: %m") : -abs(_e); })
;
95 goto finish;
96 }
97 }
98
99 k = loop_read(seed_fd, buf, buf_size, false0);
100 if (k < 0)
101 r = log_error_errno(k, "Failed to read seed from " RANDOM_SEED ": %m")({ int _level = ((3)), _e = ((k)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/random-seed/random-seed.c", 101, __func__, "Failed to read seed from "
"/var/lib/systemd/random-seed" ": %m") : -abs(_e); })
;
102 else if (k == 0) {
103 r = 0;
104 log_debug("Seed file " RANDOM_SEED " not yet initialized, proceeding.")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/random-seed/random-seed.c", 104, __func__, "Seed file "
"/var/lib/systemd/random-seed" " not yet initialized, proceeding."
) : -abs(_e); })
;
105 } else {
106 (void) lseek(seed_fd, 0, SEEK_SET0);
107
108 r = loop_write(random_fd, buf, (size_t) k, false0);
109 if (r < 0)
110 log_error_errno(r, "Failed to write seed to /dev/urandom: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/random-seed/random-seed.c", 110, __func__, "Failed to write seed to /dev/urandom: %m"
) : -abs(_e); })
;
111 }
112
113 } else if (streq(argv[1], "save")(strcmp((argv[1]),("save")) == 0)) {
114
115 seed_fd = open(RANDOM_SEED"/var/lib/systemd/random-seed", O_WRONLY01|O_CLOEXEC02000000|O_NOCTTY0400|O_CREAT0100, 0600);
116 if (seed_fd < 0) {
117 r = log_error_errno(errno, "Failed to open " RANDOM_SEED ": %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/random-seed/random-seed.c", 117,
__func__, "Failed to open " "/var/lib/systemd/random-seed" ": %m"
) : -abs(_e); })
;
118 goto finish;
119 }
120
121 random_fd = open("/dev/urandom", O_RDONLY00|O_CLOEXEC02000000|O_NOCTTY0400);
122 if (random_fd < 0) {
123 r = log_error_errno(errno, "Failed to open /dev/urandom: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm
= (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >=
((_level) & 0x07)) ? log_internal_realm(((_realm) <<
10 | (_level)), _e, "../src/random-seed/random-seed.c", 123,
__func__, "Failed to open /dev/urandom: %m") : -abs(_e); })
;
124 goto finish;
125 }
126
127 } else {
128 log_error("Unknown verb '%s'.", argv[1])({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/random-seed/random-seed.c", 128, __func__, "Unknown verb '%s'."
, argv[1]) : -abs(_e); })
;
129 r = -EINVAL22;
130 goto finish;
131 }
132
133 if (refresh_seed_file) {
134
135 /* This is just a safety measure. Given that we are root and
136 * most likely created the file ourselves the mode and owner
137 * should be correct anyway. */
138 (void) fchmod(seed_fd, 0600);
139 (void) fchown(seed_fd, 0, 0);
140
141 k = loop_read(random_fd, buf, buf_size, false0);
142 if (k < 0) {
143 r = log_error_errno(k, "Failed to read new seed from /dev/urandom: %m")({ int _level = ((3)), _e = ((k)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/random-seed/random-seed.c", 143, __func__, "Failed to read new seed from /dev/urandom: %m"
) : -abs(_e); })
;
144 goto finish;
145 }
146 if (k == 0) {
147 log_error("Got EOF while reading from /dev/urandom.")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/random-seed/random-seed.c", 147, __func__, "Got EOF while reading from /dev/urandom."
) : -abs(_e); })
;
148 r = -EIO5;
149 goto finish;
150 }
151
152 r = loop_write(seed_fd, buf, (size_t) k, false0);
153 if (r < 0)
154 log_error_errno(r, "Failed to write new random seed file: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/random-seed/random-seed.c", 154, __func__, "Failed to write new random seed file: %m"
) : -abs(_e); })
;
155 }
156
157finish:
158 return r < 0 ? EXIT_FAILURE1 : EXIT_SUCCESS0;
159}