Bug Summary

File:build-scan/../src/basic/util.c
Warning:line 354, column 29
Although the value stored to 'netnsfd' is used in the enclosing expression, the value is never actually read from 'netnsfd'

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 util.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 pic -pic-level 2 -fhalf-no-semantic-interposition -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 src/basic/libbasic.a.p -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 -I . -I .. -I /usr/include/blkid -I /usr/include/libmount -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 default -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/basic/util.c
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <alloca.h>
4#include <errno(*__errno_location ()).h>
5#include <fcntl.h>
6#include <sched.h>
7#include <signal.h>
8#include <stdarg.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12#include <sys/mman.h>
13#include <sys/prctl.h>
14#include <sys/statfs.h>
15#include <sys/sysmacros.h>
16#include <sys/types.h>
17#include <unistd.h>
18
19#include "alloc-util.h"
20#include "btrfs-util.h"
21#include "build.h"
22#include "cgroup-util.h"
23#include "def.h"
24#include "device-nodes.h"
25#include "dirent-util.h"
26#include "fd-util.h"
27#include "fileio.h"
28#include "format-util.h"
29#include "hashmap.h"
30#include "hostname-util.h"
31#include "log.h"
32#include "macro.h"
33#include "missing.h"
34#include "parse-util.h"
35#include "path-util.h"
36#include "process-util.h"
37#include "procfs-util.h"
38#include "set.h"
39#include "signal-util.h"
40#include "stat-util.h"
41#include "string-util.h"
42#include "strv.h"
43#include "time-util.h"
44#include "umask-util.h"
45#include "user-util.h"
46#include "util.h"
47#include "virt.h"
48
49int saved_argc = 0;
50char **saved_argv = NULL((void*)0);
51static int saved_in_initrd = -1;
52
53size_t page_size(void) {
54 static thread_local__thread size_t pgsz = 0;
55 long r;
56
57 if (_likely_(pgsz > 0)(__builtin_expect(!!(pgsz > 0),1)))
58 return pgsz;
59
60 r = sysconf(_SC_PAGESIZE_SC_PAGESIZE);
61 assert(r > 0)do { if ((__builtin_expect(!!(!(r > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("r > 0"), "../src/basic/util.c", 61, __PRETTY_FUNCTION__
); } while (0)
;
62
63 pgsz = (size_t) r;
64 return pgsz;
65}
66
67bool_Bool plymouth_running(void) {
68 return access("/run/plymouth/pid", F_OK0) >= 0;
69}
70
71bool_Bool display_is_local(const char *display) {
72 assert(display)do { if ((__builtin_expect(!!(!(display)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("display"), "../src/basic/util.c", 72, __PRETTY_FUNCTION__
); } while (0)
;
73
74 return
75 display[0] == ':' &&
76 display[1] >= '0' &&
77 display[1] <= '9';
78}
79
80int socket_from_display(const char *display, char **path) {
81 size_t k;
82 char *f, *c;
83
84 assert(display)do { if ((__builtin_expect(!!(!(display)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("display"), "../src/basic/util.c", 84, __PRETTY_FUNCTION__
); } while (0)
;
85 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/basic/util.c", 85, __PRETTY_FUNCTION__
); } while (0)
;
86
87 if (!display_is_local(display))
88 return -EINVAL22;
89
90 k = strspn(display+1, "0123456789");
91
92 f = new(char, STRLEN("/tmp/.X11-unix/X") + k + 1)((char*) malloc_multiply(sizeof(char), ((sizeof("""/tmp/.X11-unix/X"
"") - 1) + k + 1)))
;
93 if (!f)
94 return -ENOMEM12;
95
96 c = stpcpy(f, "/tmp/.X11-unix/X");
97 memcpy(c, display+1, k);
98 c[k] = 0;
99
100 *path = f;
101
102 return 0;
103}
104
105bool_Bool kexec_loaded(void) {
106 _cleanup_free___attribute__((cleanup(freep))) char *s = NULL((void*)0);
107
108 if (read_one_line_file("/sys/kernel/kexec_loaded", &s) < 0)
109 return false0;
110
111 return s[0] == '1';
112}
113
114int prot_from_flags(int flags) {
115
116 switch (flags & O_ACCMODE0003) {
117
118 case O_RDONLY00:
119 return PROT_READ0x1;
120
121 case O_WRONLY01:
122 return PROT_WRITE0x2;
123
124 case O_RDWR02:
125 return PROT_READ0x1|PROT_WRITE0x2;
126
127 default:
128 return -EINVAL22;
129 }
130}
131
132bool_Bool in_initrd(void) {
133 struct statfs s;
134
135 if (saved_in_initrd >= 0)
136 return saved_in_initrd;
137
138 /* We make two checks here:
139 *
140 * 1. the flag file /etc/initrd-release must exist
141 * 2. the root file system must be a memory file system
142 *
143 * The second check is extra paranoia, since misdetecting an
144 * initrd can have bad consequences due the initrd
145 * emptying when transititioning to the main systemd.
146 */
147
148 saved_in_initrd = access("/etc/initrd-release", F_OK0) >= 0 &&
149 statfs("/", &s) >= 0 &&
150 is_temporary_fs(&s);
151
152 return saved_in_initrd;
153}
154
155void in_initrd_force(bool_Bool value) {
156 saved_in_initrd = value;
157}
158
159/* hey glibc, APIs with callbacks without a user pointer are so useless */
160void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
161 int (*compar) (const void *, const void *, void *), void *arg) {
162 size_t l, u, idx;
163 const void *p;
164 int comparison;
165
166 assert(!size_multiply_overflow(nmemb, size))do { if ((__builtin_expect(!!(!(!size_multiply_overflow(nmemb
, size))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(nmemb, size)"
), "../src/basic/util.c", 166, __PRETTY_FUNCTION__); } while (
0)
;
167
168 l = 0;
169 u = nmemb;
170 while (l < u) {
171 idx = (l + u) / 2;
172 p = (const uint8_t*) base + idx * size;
173 comparison = compar(key, p, arg);
174 if (comparison < 0)
175 u = idx;
176 else if (comparison > 0)
177 l = idx + 1;
178 else
179 return (void *)p;
180 }
181 return NULL((void*)0);
182}
183
184int on_ac_power(void) {
185 bool_Bool found_offline = false0, found_online = false0;
186 _cleanup_closedir___attribute__((cleanup(closedirp))) DIR *d = NULL((void*)0);
187 struct dirent *de;
188
189 d = opendir("/sys/class/power_supply");
190 if (!d)
191 return errno(*__errno_location ()) == ENOENT2 ? true1 : -errno(*__errno_location ());
192
193 FOREACH_DIRENT(de, d, return -errno)for ((*__errno_location ()) = 0, de = readdir(d);; (*__errno_location
()) = 0, de = readdir(d)) if (!de) { if ((*__errno_location (
)) > 0) { return -(*__errno_location ()); } break; } else if
(hidden_or_backup_file((de)->d_name)) continue; else
{
194 _cleanup_close___attribute__((cleanup(closep))) int fd = -1, device = -1;
195 char contents[6];
196 ssize_t n;
197
198 device = openat(dirfd(d), de->d_name, O_DIRECTORY0200000|O_RDONLY00|O_CLOEXEC02000000|O_NOCTTY0400);
199 if (device < 0) {
200 if (IN_SET(errno, ENOENT, ENOTDIR)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended
[20 - sizeof((int[]){2, 20})/sizeof(int)]; switch((*__errno_location
())) { case 2: case 20: _found = 1; break; default: break; }
_found; })
)
201 continue;
202
203 return -errno(*__errno_location ());
204 }
205
206 fd = openat(device, "type", O_RDONLY00|O_CLOEXEC02000000|O_NOCTTY0400);
207 if (fd < 0) {
208 if (errno(*__errno_location ()) == ENOENT2)
209 continue;
210
211 return -errno(*__errno_location ());
212 }
213
214 n = read(fd, contents, sizeof(contents));
215 if (n < 0)
216 return -errno(*__errno_location ());
217
218 if (n != 6 || memcmp(contents, "Mains\n", 6))
219 continue;
220
221 safe_close(fd);
222 fd = openat(device, "online", O_RDONLY00|O_CLOEXEC02000000|O_NOCTTY0400);
223 if (fd < 0) {
224 if (errno(*__errno_location ()) == ENOENT2)
225 continue;
226
227 return -errno(*__errno_location ());
228 }
229
230 n = read(fd, contents, sizeof(contents));
231 if (n < 0)
232 return -errno(*__errno_location ());
233
234 if (n != 2 || contents[1] != '\n')
235 return -EIO5;
236
237 if (contents[0] == '1') {
238 found_online = true1;
239 break;
240 } else if (contents[0] == '0')
241 found_offline = true1;
242 else
243 return -EIO5;
244 }
245
246 return found_online || !found_offline;
247}
248
249int container_get_leader(const char *machine, pid_t *pid) {
250 _cleanup_free___attribute__((cleanup(freep))) char *s = NULL((void*)0), *class = NULL((void*)0);
251 const char *p;
252 pid_t leader;
253 int r;
254
255 assert(machine)do { if ((__builtin_expect(!!(!(machine)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("machine"), "../src/basic/util.c", 255, __PRETTY_FUNCTION__
); } while (0)
;
256 assert(pid)do { if ((__builtin_expect(!!(!(pid)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("pid"), "../src/basic/util.c", 256, __PRETTY_FUNCTION__
); } while (0)
;
257
258 if (streq(machine, ".host")(strcmp((machine),(".host")) == 0)) {
259 *pid = 1;
260 return 0;
261 }
262
263 if (!machine_name_is_valid(machine)hostname_is_valid(machine, 0))
264 return -EINVAL22;
265
266 p = strjoina("/run/systemd/machines/", machine)({ const char *_appendees_[] = { "/run/systemd/machines/", machine
}; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ =
0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_
)/sizeof((_appendees_)[0]), ((void)0))) && _appendees_
[_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca
(_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(_appendees_), typeof(&
*(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0]
), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy
(_p_, _appendees_[_i_]); *_p_ = 0; _d_; })
;
267 r = parse_env_file(NULL((void*)0), p, NEWLINE"\n\r", "LEADER", &s, "CLASS", &class, NULL((void*)0));
268 if (r == -ENOENT2)
269 return -EHOSTDOWN112;
270 if (r < 0)
271 return r;
272 if (!s)
273 return -EIO5;
274
275 if (!streq_ptr(class, "container"))
276 return -EIO5;
277
278 r = parse_pid(s, &leader);
279 if (r < 0)
280 return r;
281 if (leader <= 1)
282 return -EIO5;
283
284 *pid = leader;
285 return 0;
286}
287
288int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd) {
289 _cleanup_close___attribute__((cleanup(closep))) int pidnsfd = -1, mntnsfd = -1, netnsfd = -1, usernsfd = -1;
290 int rfd = -1;
291
292 assert(pid >= 0)do { if ((__builtin_expect(!!(!(pid >= 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("pid >= 0"), "../src/basic/util.c", 292
, __PRETTY_FUNCTION__); } while (0)
;
293
294 if (mntns_fd) {
295 const char *mntns;
296
297 mntns = procfs_file_alloca(pid, "ns/mnt")({ pid_t _pid_ = (pid); const char *_r_; if (_pid_ == 0) { _r_
= ("/proc/self/" "ns/mnt"); } else { _r_ = __builtin_alloca (
(sizeof("""/proc/""") - 1) + (2+(sizeof(pid_t) <= 1 ? 3 : sizeof
(pid_t) <= 2 ? 5 : sizeof(pid_t) <= 4 ? 10 : sizeof(pid_t
) <= 8 ? 20 : sizeof(int[-2*(sizeof(pid_t) > 8)]))) + 1
+ sizeof("ns/mnt")); sprintf((char*) _r_, "/proc/""%" "i""/"
"ns/mnt", _pid_); } _r_; })
;
298 mntnsfd = open(mntns, O_RDONLY00|O_NOCTTY0400|O_CLOEXEC02000000);
299 if (mntnsfd < 0)
300 return -errno(*__errno_location ());
301 }
302
303 if (pidns_fd) {
304 const char *pidns;
305
306 pidns = procfs_file_alloca(pid, "ns/pid")({ pid_t _pid_ = (pid); const char *_r_; if (_pid_ == 0) { _r_
= ("/proc/self/" "ns/pid"); } else { _r_ = __builtin_alloca (
(sizeof("""/proc/""") - 1) + (2+(sizeof(pid_t) <= 1 ? 3 : sizeof
(pid_t) <= 2 ? 5 : sizeof(pid_t) <= 4 ? 10 : sizeof(pid_t
) <= 8 ? 20 : sizeof(int[-2*(sizeof(pid_t) > 8)]))) + 1
+ sizeof("ns/pid")); sprintf((char*) _r_, "/proc/""%" "i""/"
"ns/pid", _pid_); } _r_; })
;
307 pidnsfd = open(pidns, O_RDONLY00|O_NOCTTY0400|O_CLOEXEC02000000);
308 if (pidnsfd < 0)
309 return -errno(*__errno_location ());
310 }
311
312 if (netns_fd) {
313 const char *netns;
314
315 netns = procfs_file_alloca(pid, "ns/net")({ pid_t _pid_ = (pid); const char *_r_; if (_pid_ == 0) { _r_
= ("/proc/self/" "ns/net"); } else { _r_ = __builtin_alloca (
(sizeof("""/proc/""") - 1) + (2+(sizeof(pid_t) <= 1 ? 3 : sizeof
(pid_t) <= 2 ? 5 : sizeof(pid_t) <= 4 ? 10 : sizeof(pid_t
) <= 8 ? 20 : sizeof(int[-2*(sizeof(pid_t) > 8)]))) + 1
+ sizeof("ns/net")); sprintf((char*) _r_, "/proc/""%" "i""/"
"ns/net", _pid_); } _r_; })
;
316 netnsfd = open(netns, O_RDONLY00|O_NOCTTY0400|O_CLOEXEC02000000);
317 if (netnsfd < 0)
318 return -errno(*__errno_location ());
319 }
320
321 if (userns_fd) {
322 const char *userns;
323
324 userns = procfs_file_alloca(pid, "ns/user")({ pid_t _pid_ = (pid); const char *_r_; if (_pid_ == 0) { _r_
= ("/proc/self/" "ns/user"); } else { _r_ = __builtin_alloca
((sizeof("""/proc/""") - 1) + (2+(sizeof(pid_t) <= 1 ? 3 :
sizeof(pid_t) <= 2 ? 5 : sizeof(pid_t) <= 4 ? 10 : sizeof
(pid_t) <= 8 ? 20 : sizeof(int[-2*(sizeof(pid_t) > 8)])
)) + 1 + sizeof("ns/user")); sprintf((char*) _r_, "/proc/""%"
"i""/" "ns/user", _pid_); } _r_; })
;
325 usernsfd = open(userns, O_RDONLY00|O_NOCTTY0400|O_CLOEXEC02000000);
326 if (usernsfd < 0 && errno(*__errno_location ()) != ENOENT2)
327 return -errno(*__errno_location ());
328 }
329
330 if (root_fd) {
331 const char *root;
332
333 root = procfs_file_alloca(pid, "root")({ pid_t _pid_ = (pid); const char *_r_; if (_pid_ == 0) { _r_
= ("/proc/self/" "root"); } else { _r_ = __builtin_alloca ((
sizeof("""/proc/""") - 1) + (2+(sizeof(pid_t) <= 1 ? 3 : sizeof
(pid_t) <= 2 ? 5 : sizeof(pid_t) <= 4 ? 10 : sizeof(pid_t
) <= 8 ? 20 : sizeof(int[-2*(sizeof(pid_t) > 8)]))) + 1
+ sizeof("root")); sprintf((char*) _r_, "/proc/""%" "i""/" "root"
, _pid_); } _r_; })
;
334 rfd = open(root, O_RDONLY00|O_NOCTTY0400|O_CLOEXEC02000000|O_DIRECTORY0200000);
335 if (rfd < 0)
336 return -errno(*__errno_location ());
337 }
338
339 if (pidns_fd)
340 *pidns_fd = pidnsfd;
341
342 if (mntns_fd)
343 *mntns_fd = mntnsfd;
344
345 if (netns_fd)
346 *netns_fd = netnsfd;
347
348 if (userns_fd)
349 *userns_fd = usernsfd;
350
351 if (root_fd)
352 *root_fd = rfd;
353
354 pidnsfd = mntnsfd = netnsfd = usernsfd = -1;
Although the value stored to 'netnsfd' is used in the enclosing expression, the value is never actually read from 'netnsfd'
355
356 return 0;
357}
358
359int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd) {
360 if (userns_fd >= 0) {
361 /* Can't setns to your own userns, since then you could
362 * escalate from non-root to root in your own namespace, so
363 * check if namespaces equal before attempting to enter. */
364 _cleanup_free___attribute__((cleanup(freep))) char *userns_fd_path = NULL((void*)0);
365 int r;
366 if (asprintf(&userns_fd_path, "/proc/self/fd/%d", userns_fd) < 0)
367 return -ENOMEM12;
368
369 r = files_same(userns_fd_path, "/proc/self/ns/user", 0);
370 if (r < 0)
371 return r;
372 if (r)
373 userns_fd = -1;
374 }
375
376 if (pidns_fd >= 0)
377 if (setns(pidns_fd, CLONE_NEWPID0x20000000) < 0)
378 return -errno(*__errno_location ());
379
380 if (mntns_fd >= 0)
381 if (setns(mntns_fd, CLONE_NEWNS0x00020000) < 0)
382 return -errno(*__errno_location ());
383
384 if (netns_fd >= 0)
385 if (setns(netns_fd, CLONE_NEWNET0x40000000) < 0)
386 return -errno(*__errno_location ());
387
388 if (userns_fd >= 0)
389 if (setns(userns_fd, CLONE_NEWUSER0x10000000) < 0)
390 return -errno(*__errno_location ());
391
392 if (root_fd >= 0) {
393 if (fchdir(root_fd) < 0)
394 return -errno(*__errno_location ());
395
396 if (chroot(".") < 0)
397 return -errno(*__errno_location ());
398 }
399
400 return reset_uid_gid();
401}
402
403uint64_t physical_memory(void) {
404 _cleanup_free___attribute__((cleanup(freep))) char *root = NULL((void*)0), *value = NULL((void*)0);
405 uint64_t mem, lim;
406 size_t ps;
407 long sc;
408 int r;
409
410 /* We return this as uint64_t in case we are running as 32bit process on a 64bit kernel with huge amounts of
411 * memory.
412 *
413 * In order to support containers nicely that have a configured memory limit we'll take the minimum of the
414 * physically reported amount of memory and the limit configured for the root cgroup, if there is any. */
415
416 sc = sysconf(_SC_PHYS_PAGES_SC_PHYS_PAGES);
417 assert(sc > 0)do { if ((__builtin_expect(!!(!(sc > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("sc > 0"), "../src/basic/util.c", 417
, __PRETTY_FUNCTION__); } while (0)
;
418
419 ps = page_size();
420 mem = (uint64_t) sc * (uint64_t) ps;
421
422 r = cg_get_root_path(&root);
423 if (r < 0) {
424 log_debug_errno(r, "Failed to determine root cgroup, ignoring cgroup memory limit: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/basic/util.c", 424, __func__, "Failed to determine root cgroup, ignoring cgroup memory limit: %m"
) : -abs(_e); })
;
425 return mem;
426 }
427
428 r = cg_all_unified();
429 if (r < 0) {
430 log_debug_errno(r, "Failed to determine root unified mode, ignoring cgroup memory limit: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/basic/util.c", 430, __func__, "Failed to determine root unified mode, ignoring cgroup memory limit: %m"
) : -abs(_e); })
;
431 return mem;
432 }
433 if (r > 0) {
434 r = cg_get_attribute("memory", root, "memory.max", &value);
435 if (r < 0) {
436 log_debug_errno(r, "Failed to read memory.max cgroup attribute, ignoring cgroup memory limit: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/basic/util.c", 436, __func__, "Failed to read memory.max cgroup attribute, ignoring cgroup memory limit: %m"
) : -abs(_e); })
;
437 return mem;
438 }
439
440 if (streq(value, "max")(strcmp((value),("max")) == 0))
441 return mem;
442 } else {
443 r = cg_get_attribute("memory", root, "memory.limit_in_bytes", &value);
444 if (r < 0) {
445 log_debug_errno(r, "Failed to read memory.limit_in_bytes cgroup attribute, ignoring cgroup memory limit: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/basic/util.c", 445, __func__, "Failed to read memory.limit_in_bytes cgroup attribute, ignoring cgroup memory limit: %m"
) : -abs(_e); })
;
446 return mem;
447 }
448 }
449
450 r = safe_atou64(value, &lim);
451 if (r < 0) {
452 log_debug_errno(r, "Failed to parse cgroup memory limit '%s', ignoring: %m", value)({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/basic/util.c", 452, __func__, "Failed to parse cgroup memory limit '%s', ignoring: %m"
, value) : -abs(_e); })
;
453 return mem;
454 }
455 if (lim == UINT64_MAX(18446744073709551615UL))
456 return mem;
457
458 /* Make sure the limit is a multiple of our own page size */
459 lim /= ps;
460 lim *= ps;
461
462 return MIN(mem, lim)__extension__ ({ const typeof((mem)) __unique_prefix_A27 = ((
mem)); const typeof((lim)) __unique_prefix_B28 = ((lim)); __unique_prefix_A27
< __unique_prefix_B28 ? __unique_prefix_A27 : __unique_prefix_B28
; })
;
463}
464
465uint64_t physical_memory_scale(uint64_t v, uint64_t max) {
466 uint64_t p, m, ps, r;
467
468 assert(max > 0)do { if ((__builtin_expect(!!(!(max > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("max > 0"), "../src/basic/util.c", 468
, __PRETTY_FUNCTION__); } while (0)
;
469
470 /* Returns the physical memory size, multiplied by v divided by max. Returns UINT64_MAX on overflow. On success
471 * the result is a multiple of the page size (rounds down). */
472
473 ps = page_size();
474 assert(ps > 0)do { if ((__builtin_expect(!!(!(ps > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ps > 0"), "../src/basic/util.c", 474
, __PRETTY_FUNCTION__); } while (0)
;
475
476 p = physical_memory() / ps;
477 assert(p > 0)do { if ((__builtin_expect(!!(!(p > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("p > 0"), "../src/basic/util.c", 477,
__PRETTY_FUNCTION__); } while (0)
;
478
479 m = p * v;
480 if (m / p != v)
481 return UINT64_MAX(18446744073709551615UL);
482
483 m /= max;
484
485 r = m * ps;
486 if (r / ps != m)
487 return UINT64_MAX(18446744073709551615UL);
488
489 return r;
490}
491
492uint64_t system_tasks_max(void) {
493
494 uint64_t a = TASKS_MAX4194303U, b = TASKS_MAX4194303U;
495 _cleanup_free___attribute__((cleanup(freep))) char *root = NULL((void*)0);
496 int r;
497
498 /* Determine the maximum number of tasks that may run on this system. We check three sources to determine this
499 * limit:
500 *
501 * a) the maximum tasks value the kernel allows on this architecture
502 * b) the cgroups pids_max attribute for the system
503 * c) the kernel's configured maximum PID value
504 *
505 * And then pick the smallest of the three */
506
507 r = procfs_tasks_get_limit(&a);
508 if (r < 0)
509 log_debug_errno(r, "Failed to read maximum number of tasks from /proc, ignoring: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/basic/util.c", 509, __func__, "Failed to read maximum number of tasks from /proc, ignoring: %m"
) : -abs(_e); })
;
510
511 r = cg_get_root_path(&root);
512 if (r < 0)
513 log_debug_errno(r, "Failed to determine cgroup root path, ignoring: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/basic/util.c", 513, __func__, "Failed to determine cgroup root path, ignoring: %m"
) : -abs(_e); })
;
514 else {
515 _cleanup_free___attribute__((cleanup(freep))) char *value = NULL((void*)0);
516
517 r = cg_get_attribute("pids", root, "pids.max", &value);
518 if (r < 0)
519 log_debug_errno(r, "Failed to read pids.max attribute of cgroup root, ignoring: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/basic/util.c", 519, __func__, "Failed to read pids.max attribute of cgroup root, ignoring: %m"
) : -abs(_e); })
;
520 else if (!streq(value, "max")(strcmp((value),("max")) == 0)) {
521 r = safe_atou64(value, &b);
522 if (r < 0)
523 log_debug_errno(r, "Failed to parse pids.max attribute of cgroup root, ignoring: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/basic/util.c", 523, __func__, "Failed to parse pids.max attribute of cgroup root, ignoring: %m"
) : -abs(_e); })
;
524 }
525 }
526
527 return MIN3(TASKS_MAX,__extension__ ({ const typeof(4194303U) _c = __extension__ ({
const typeof((4194303U)) __unique_prefix_A29 = ((4194303U));
const typeof((a <= 0 ? 4194303U : a)) __unique_prefix_B30
= ((a <= 0 ? 4194303U : a)); __unique_prefix_A29 < __unique_prefix_B30
? __unique_prefix_A29 : __unique_prefix_B30; }); __extension__
({ const typeof((_c)) __unique_prefix_A31 = ((_c)); const typeof
((b <= 0 ? 4194303U : b)) __unique_prefix_B32 = ((b <= 0
? 4194303U : b)); __unique_prefix_A31 < __unique_prefix_B32
? __unique_prefix_A31 : __unique_prefix_B32; }); })
528 a <= 0 ? TASKS_MAX : a,__extension__ ({ const typeof(4194303U) _c = __extension__ ({
const typeof((4194303U)) __unique_prefix_A29 = ((4194303U));
const typeof((a <= 0 ? 4194303U : a)) __unique_prefix_B30
= ((a <= 0 ? 4194303U : a)); __unique_prefix_A29 < __unique_prefix_B30
? __unique_prefix_A29 : __unique_prefix_B30; }); __extension__
({ const typeof((_c)) __unique_prefix_A31 = ((_c)); const typeof
((b <= 0 ? 4194303U : b)) __unique_prefix_B32 = ((b <= 0
? 4194303U : b)); __unique_prefix_A31 < __unique_prefix_B32
? __unique_prefix_A31 : __unique_prefix_B32; }); })
529 b <= 0 ? TASKS_MAX : b)__extension__ ({ const typeof(4194303U) _c = __extension__ ({
const typeof((4194303U)) __unique_prefix_A29 = ((4194303U));
const typeof((a <= 0 ? 4194303U : a)) __unique_prefix_B30
= ((a <= 0 ? 4194303U : a)); __unique_prefix_A29 < __unique_prefix_B30
? __unique_prefix_A29 : __unique_prefix_B30; }); __extension__
({ const typeof((_c)) __unique_prefix_A31 = ((_c)); const typeof
((b <= 0 ? 4194303U : b)) __unique_prefix_B32 = ((b <= 0
? 4194303U : b)); __unique_prefix_A31 < __unique_prefix_B32
? __unique_prefix_A31 : __unique_prefix_B32; }); })
;
530}
531
532uint64_t system_tasks_max_scale(uint64_t v, uint64_t max) {
533 uint64_t t, m;
534
535 assert(max > 0)do { if ((__builtin_expect(!!(!(max > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("max > 0"), "../src/basic/util.c", 535
, __PRETTY_FUNCTION__); } while (0)
;
536
537 /* Multiply the system's task value by the fraction v/max. Hence, if max==100 this calculates percentages
538 * relative to the system's maximum number of tasks. Returns UINT64_MAX on overflow. */
539
540 t = system_tasks_max();
541 assert(t > 0)do { if ((__builtin_expect(!!(!(t > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("t > 0"), "../src/basic/util.c", 541,
__PRETTY_FUNCTION__); } while (0)
;
542
543 m = t * v;
544 if (m / t != v) /* overflow? */
545 return UINT64_MAX(18446744073709551615UL);
546
547 return m / max;
548}
549
550int version(void) {
551 puts(PACKAGE_STRING"systemd 239" "\n"
552 SYSTEMD_FEATURES"+PAM" " " "+AUDIT" " " "+SELINUX" " " "+IMA" " " "-APPARMOR"
" " "+SMACK" " " "+SYSVINIT" " " "+UTMP" " " "+LIBCRYPTSETUP"
" " "+GCRYPT" " " "+GNUTLS" " " "+ACL" " " "+XZ" " " "+LZ4" " "
"+SECCOMP" " " "+BLKID" " " "+ELFUTILS" " " "+KMOD" " " "+IDN2"
" " "-IDN" " " "+PCRE2" " " "default-hierarchy=" "hybrid"
);
553 return 0;
554}
555
556/* This is a direct translation of str_verscmp from boot.c */
557static bool_Bool is_digit(int c) {
558 return c >= '0' && c <= '9';
559}
560
561static int c_order(int c) {
562 if (c == 0 || is_digit(c))
563 return 0;
564
565 if ((c >= 'a') && (c <= 'z'))
566 return c;
567
568 return c + 0x10000;
569}
570
571int str_verscmp(const char *s1, const char *s2) {
572 const char *os1, *os2;
573
574 assert(s1)do { if ((__builtin_expect(!!(!(s1)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s1"), "../src/basic/util.c", 574, __PRETTY_FUNCTION__
); } while (0)
;
575 assert(s2)do { if ((__builtin_expect(!!(!(s2)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("s2"), "../src/basic/util.c", 575, __PRETTY_FUNCTION__
); } while (0)
;
576
577 os1 = s1;
578 os2 = s2;
579
580 while (*s1 || *s2) {
581 int first;
582
583 while ((*s1 && !is_digit(*s1)) || (*s2 && !is_digit(*s2))) {
584 int order;
585
586 order = c_order(*s1) - c_order(*s2);
587 if (order != 0)
588 return order;
589 s1++;
590 s2++;
591 }
592
593 while (*s1 == '0')
594 s1++;
595 while (*s2 == '0')
596 s2++;
597
598 first = 0;
599 while (is_digit(*s1) && is_digit(*s2)) {
600 if (first == 0)
601 first = *s1 - *s2;
602 s1++;
603 s2++;
604 }
605
606 if (is_digit(*s1))
607 return 1;
608 if (is_digit(*s2))
609 return -1;
610
611 if (first != 0)
612 return first;
613 }
614
615 return strcmp(os1, os2);
616}
617
618/* Turn off core dumps but only if we're running outside of a container. */
619void disable_coredumps(void) {
620 int r;
621
622 if (detect_container() > 0)
623 return;
624
625 r = write_string_file("/proc/sys/kernel/core_pattern", "|/bin/false", 0);
626 if (r < 0)
627 log_debug_errno(r, "Failed to turn off coredumps, ignoring: %m")({ int _level = ((7)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD
); (log_get_max_level_realm(_realm) >= ((_level) & 0x07
)) ? log_internal_realm(((_realm) << 10 | (_level)), _e
, "../src/basic/util.c", 627, __func__, "Failed to turn off coredumps, ignoring: %m"
) : -abs(_e); })
;
628}