Bug Summary

File:build-scan/../src/basic/util.c
Warning:line 354, column 9
Value stored to 'pidnsfd' is never read

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;
Value stored to 'pidnsfd' is never read
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_A15 = ((
mem)); const typeof((lim)) __unique_prefix_B16 = ((lim)); __unique_prefix_A15
< __unique_prefix_B16 ? __unique_prefix_A15 : __unique_prefix_B16
; })
;
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_A17 = ((4194303U));
const typeof((a <= 0 ? 4194303U : a)) __unique_prefix_B18
= ((a <= 0 ? 4194303U : a)); __unique_prefix_A17 < __unique_prefix_B18
? __unique_prefix_A17 : __unique_prefix_B18; }); __extension__
({ const typeof((_c)) __unique_prefix_A19 = ((_c)); const typeof
((b <= 0 ? 4194303U : b)) __unique_prefix_B20 = ((b <= 0
? 4194303U : b)); __unique_prefix_A19 < __unique_prefix_B20
? __unique_prefix_A19 : __unique_prefix_B20; }); })
528 a <= 0 ? TASKS_MAX : a,__extension__ ({ const typeof(4194303U) _c = __extension__ ({
const typeof((4194303U)) __unique_prefix_A17 = ((4194303U));
const typeof((a <= 0 ? 4194303U : a)) __unique_prefix_B18
= ((a <= 0 ? 4194303U : a)); __unique_prefix_A17 < __unique_prefix_B18
? __unique_prefix_A17 : __unique_prefix_B18; }); __extension__
({ const typeof((_c)) __unique_prefix_A19 = ((_c)); const typeof
((b <= 0 ? 4194303U : b)) __unique_prefix_B20 = ((b <= 0
? 4194303U : b)); __unique_prefix_A19 < __unique_prefix_B20
? __unique_prefix_A19 : __unique_prefix_B20; }); })
529 b <= 0 ? TASKS_MAX : b)__extension__ ({ const typeof(4194303U) _c = __extension__ ({
const typeof((4194303U)) __unique_prefix_A17 = ((4194303U));
const typeof((a <= 0 ? 4194303U : a)) __unique_prefix_B18
= ((a <= 0 ? 4194303U : a)); __unique_prefix_A17 < __unique_prefix_B18
? __unique_prefix_A17 : __unique_prefix_B18; }); __extension__
({ const typeof((_c)) __unique_prefix_A19 = ((_c)); const typeof
((b <= 0 ? 4194303U : b)) __unique_prefix_B20 = ((b <= 0
? 4194303U : b)); __unique_prefix_A19 < __unique_prefix_B20
? __unique_prefix_A19 : __unique_prefix_B20; }); })
;
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}