Bug Summary

File:build-scan/../src/analyze/analyze-security.c
Warning:line 1417, column 62
Potential leak of memory pointed to by 'd'

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 analyze-security.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-analyze.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 -I /usr/include/libmount -I /usr/include/blkid -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/analyze/analyze-security.c
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <sched.h>
4#include <sys/utsname.h>
5
6#include "analyze-security.h"
7#include "bus-error.h"
8#include "bus-unit-util.h"
9#include "bus-util.h"
10#include "env-util.h"
11#include "format-table.h"
12#include "in-addr-util.h"
13#include "locale-util.h"
14#include "macro.h"
15#include "parse-util.h"
16#include "path-util.h"
17#include "seccomp-util.h"
18#include "set.h"
19#include "stdio-util.h"
20#include "strv.h"
21#include "terminal-util.h"
22#include "unit-def.h"
23#include "unit-name.h"
24
25struct security_info {
26 char *id;
27 char *type;
28 char *load_state;
29 char *fragment_path;
30 bool_Bool default_dependencies;
31
32 uint64_t ambient_capabilities;
33 uint64_t capability_bounding_set;
34
35 char *user;
36 char **supplementary_groups;
37 bool_Bool dynamic_user;
38
39 bool_Bool ip_address_deny_all;
40 bool_Bool ip_address_allow_localhost;
41 bool_Bool ip_address_allow_other;
42
43 char *keyring_mode;
44 bool_Bool lock_personality;
45 bool_Bool memory_deny_write_execute;
46 bool_Bool no_new_privileges;
47 char *notify_access;
48
49 bool_Bool private_devices;
50 bool_Bool private_mounts;
51 bool_Bool private_network;
52 bool_Bool private_tmp;
53 bool_Bool private_users;
54
55 bool_Bool protect_control_groups;
56 bool_Bool protect_kernel_modules;
57 bool_Bool protect_kernel_tunables;
58
59 char *protect_home;
60 char *protect_system;
61
62 bool_Bool remove_ipc;
63
64 bool_Bool restrict_address_family_inet;
65 bool_Bool restrict_address_family_unix;
66 bool_Bool restrict_address_family_netlink;
67 bool_Bool restrict_address_family_packet;
68 bool_Bool restrict_address_family_other;
69
70 uint64_t restrict_namespaces;
71 bool_Bool restrict_realtime;
72 bool_Bool restrict_suid_sgid;
73
74 char *root_directory;
75 char *root_image;
76
77 bool_Bool delegate;
78 char *device_policy;
79 bool_Bool device_allow_non_empty;
80
81 char **system_call_architectures;
82
83 bool_Bool system_call_filter_whitelist;
84 Set *system_call_filter;
85
86 uint32_t _umask;
87};
88
89struct security_assessor {
90 const char *id;
91 const char *description_good;
92 const char *description_bad;
93 const char *description_na;
94 const char *url;
95 uint64_t weight;
96 uint64_t range;
97 int (*assess)(const struct security_assessor *a, const struct security_info *info, const void *data, uint64_t *ret_badness, char **ret_description);
98 size_t offset;
99 uint64_t parameter;
100 bool_Bool default_dependencies_only;
101};
102
103static void security_info_free(struct security_info *i) {
104 if (!i)
105 return;
106
107 free(i->id);
108 free(i->type);
109 free(i->load_state);
110 free(i->fragment_path);
111
112 free(i->user);
113
114 free(i->protect_home);
115 free(i->protect_system);
116
117 free(i->root_directory);
118 free(i->root_image);
119
120 free(i->keyring_mode);
121 free(i->notify_access);
122
123 free(i->device_policy);
124
125 strv_free(i->supplementary_groups);
126 strv_free(i->system_call_architectures);
127
128 set_free_free(i->system_call_filter);
129}
130
131static bool_Bool security_info_runs_privileged(const struct security_info *i) {
132 assert(i)do { if ((__builtin_expect(!!(!(i)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("i"), "../src/analyze/analyze-security.c"
, 132, __PRETTY_FUNCTION__); } while (0)
;
133
134 if (STRPTR_IN_SET(i->user, "0", "root")({ const char* _x = (i->user); _x && (!!strv_find(
(((char**) ((const char*[]) { "0", "root", ((void*)0) }))), (
_x))); })
)
135 return true1;
136
137 if (i->dynamic_user)
138 return false0;
139
140 return isempty(i->user);
141}
142
143static int assess_bool(
144 const struct security_assessor *a,
145 const struct security_info *info,
146 const void *data,
147 uint64_t *ret_badness,
148 char **ret_description) {
149
150 const bool_Bool *b = data;
151
152 assert(b)do { if ((__builtin_expect(!!(!(b)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("b"), "../src/analyze/analyze-security.c"
, 152, __PRETTY_FUNCTION__); } while (0)
;
153 assert(ret_badness)do { if ((__builtin_expect(!!(!(ret_badness)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_badness"), "../src/analyze/analyze-security.c"
, 153, __PRETTY_FUNCTION__); } while (0)
;
154 assert(ret_description)do { if ((__builtin_expect(!!(!(ret_description)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_description"), "../src/analyze/analyze-security.c"
, 154, __PRETTY_FUNCTION__); } while (0)
;
155
156 *ret_badness = a->parameter ? *b : !*b;
157 *ret_description = NULL((void*)0);
158
159 return 0;
160}
161
162static int assess_user(
163 const struct security_assessor *a,
164 const struct security_info *info,
165 const void *data,
166 uint64_t *ret_badness,
167 char **ret_description) {
168
169 _cleanup_free___attribute__((cleanup(freep))) char *d = NULL((void*)0);
170 uint64_t b;
171
172 assert(ret_badness)do { if ((__builtin_expect(!!(!(ret_badness)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_badness"), "../src/analyze/analyze-security.c"
, 172, __PRETTY_FUNCTION__); } while (0)
;
173 assert(ret_description)do { if ((__builtin_expect(!!(!(ret_description)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_description"), "../src/analyze/analyze-security.c"
, 173, __PRETTY_FUNCTION__); } while (0)
;
174
175 if (streq_ptr(info->user, NOBODY_USER_NAME"nobody")) {
176 d = strdup("Service runs under as '" NOBODY_USER_NAME"nobody" "' user, which should not be used for services");
177 b = 9;
178 } else if (info->dynamic_user && !STR_IN_SET(info->user, "0", "root")(!!strv_find((((char**) ((const char*[]) { "0", "root", ((void
*)0) }))), (info->user)))
) {
179 d = strdup("Service runs under a transient non-root user identity");
180 b = 0;
181 } else if (info->user && !STR_IN_SET(info->user, "0", "root", "")(!!strv_find((((char**) ((const char*[]) { "0", "root", "", (
(void*)0) }))), (info->user)))
) {
182 d = strdup("Service runs under a static non-root user identity");
183 b = 0;
184 } else {
185 *ret_badness = 10;
186 *ret_description = NULL((void*)0);
187 return 0;
188 }
189
190 if (!d)
191 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/analyze/analyze-security.c"
, 191, __func__)
;
192
193 *ret_badness = b;
194 *ret_description = TAKE_PTR(d)({ typeof(d) _ptr_ = (d); (d) = ((void*)0); _ptr_; });
195
196 return 0;
197}
198
199static int assess_protect_home(
200 const struct security_assessor *a,
201 const struct security_info *info,
202 const void *data,
203 uint64_t *ret_badness,
204 char **ret_description) {
205
206 const char *description;
207 uint64_t badness;
208 char *copy;
209 int r;
210
211 assert(ret_badness)do { if ((__builtin_expect(!!(!(ret_badness)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_badness"), "../src/analyze/analyze-security.c"
, 211, __PRETTY_FUNCTION__); } while (0)
;
212 assert(ret_description)do { if ((__builtin_expect(!!(!(ret_description)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_description"), "../src/analyze/analyze-security.c"
, 212, __PRETTY_FUNCTION__); } while (0)
;
213
214 badness = 10;
215 description = "Service has full access to home directories";
216
217 r = parse_boolean(info->protect_home);
218 if (r < 0) {
219 if (streq_ptr(info->protect_home, "read-only")) {
220 badness = 5;
221 description = "Service has read-only access to home directories";
222 } else if (streq_ptr(info->protect_home, "tmpfs")) {
223 badness = 1;
224 description = "Service has access to fake empty home directories";
225 }
226 } else if (r > 0) {
227 badness = 0;
228 description = "Service has no access to home directories";
229 }
230
231 copy = strdup(description);
232 if (!copy)
233 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/analyze/analyze-security.c"
, 233, __func__)
;
234
235 *ret_badness = badness;
236 *ret_description = copy;
237
238 return 0;
239}
240
241static int assess_protect_system(
242 const struct security_assessor *a,
243 const struct security_info *info,
244 const void *data,
245 uint64_t *ret_badness,
246 char **ret_description) {
247
248 const char *description;
249 uint64_t badness;
250 char *copy;
251 int r;
252
253 assert(ret_badness)do { if ((__builtin_expect(!!(!(ret_badness)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_badness"), "../src/analyze/analyze-security.c"
, 253, __PRETTY_FUNCTION__); } while (0)
;
254 assert(ret_description)do { if ((__builtin_expect(!!(!(ret_description)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_description"), "../src/analyze/analyze-security.c"
, 254, __PRETTY_FUNCTION__); } while (0)
;
255
256 badness = 10;
257 description = "Service has full access the OS file hierarchy";
258
259 r = parse_boolean(info->protect_system);
260 if (r < 0) {
261 if (streq_ptr(info->protect_system, "full")) {
262 badness = 3;
263 description = "Service has very limited write access to OS file hierarchy";
264 } else if (streq_ptr(info->protect_system, "strict")) {
265 badness = 0;
266 description = "Service has strict read-only access to the OS file hierarchy";
267 }
268 } else if (r > 0) {
269 badness = 5;
270 description = "Service has limited write access to the OS file hierarchy";
271 }
272
273 copy = strdup(description);
274 if (!copy)
275 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/analyze/analyze-security.c"
, 275, __func__)
;
276
277 *ret_badness = badness;
278 *ret_description = copy;
279
280 return 0;
281}
282
283static int assess_root_directory(
284 const struct security_assessor *a,
285 const struct security_info *info,
286 const void *data,
287 uint64_t *ret_badness,
288 char **ret_description) {
289
290 assert(ret_badness)do { if ((__builtin_expect(!!(!(ret_badness)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_badness"), "../src/analyze/analyze-security.c"
, 290, __PRETTY_FUNCTION__); } while (0)
;
291 assert(ret_description)do { if ((__builtin_expect(!!(!(ret_description)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_description"), "../src/analyze/analyze-security.c"
, 291, __PRETTY_FUNCTION__); } while (0)
;
292
293 *ret_badness =
294 (isempty(info->root_directory) ||
295 path_equal(info->root_directory, "/")) &&
296 (isempty(info->root_image) ||
297 path_equal(info->root_image, "/"));
298 *ret_description = NULL((void*)0);
299
300 return 0;
301}
302
303static int assess_capability_bounding_set(
304 const struct security_assessor *a,
305 const struct security_info *info,
306 const void *data,
307 uint64_t *ret_badness,
308 char **ret_description) {
309
310 assert(ret_badness)do { if ((__builtin_expect(!!(!(ret_badness)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_badness"), "../src/analyze/analyze-security.c"
, 310, __PRETTY_FUNCTION__); } while (0)
;
311 assert(ret_description)do { if ((__builtin_expect(!!(!(ret_description)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_description"), "../src/analyze/analyze-security.c"
, 311, __PRETTY_FUNCTION__); } while (0)
;
312
313 *ret_badness = !!(info->capability_bounding_set & a->parameter);
314 *ret_description = NULL((void*)0);
315
316 return 0;
317}
318
319static int assess_umask(
320 const struct security_assessor *a,
321 const struct security_info *info,
322 const void *data,
323 uint64_t *ret_badness,
324 char **ret_description) {
325
326 char *copy = NULL((void*)0);
327 const char *d;
328 uint64_t b;
329
330 assert(ret_badness)do { if ((__builtin_expect(!!(!(ret_badness)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_badness"), "../src/analyze/analyze-security.c"
, 330, __PRETTY_FUNCTION__); } while (0)
;
331 assert(ret_description)do { if ((__builtin_expect(!!(!(ret_description)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_description"), "../src/analyze/analyze-security.c"
, 331, __PRETTY_FUNCTION__); } while (0)
;
332
333 if (!FLAGS_SET(info->_umask, 0002)(((info->_umask) & (0002)) == (0002))) {
334 d = "Files created by service are world-writable by default";
335 b = 10;
336 } else if (!FLAGS_SET(info->_umask, 0004)(((info->_umask) & (0004)) == (0004))) {
337 d = "Files created by service are world-readable by default";
338 b = 5;
339 } else if (!FLAGS_SET(info->_umask, 0020)(((info->_umask) & (0020)) == (0020))) {
340 d = "Files created by service are group-writable by default";
341 b = 2;
342 } else if (!FLAGS_SET(info->_umask, 0040)(((info->_umask) & (0040)) == (0040))) {
343 d = "Files created by service are group-readable by default";
344 b = 1;
345 } else {
346 d = "Files created by service are accessible only by service's own user by default";
347 b = 0;
348 }
349
350 copy = strdup(d);
351 if (!copy)
352 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/analyze/analyze-security.c"
, 352, __func__)
;
353
354 *ret_badness = b;
355 *ret_description = copy;
356
357 return 0;
358}
359
360static int assess_keyring_mode(
361 const struct security_assessor *a,
362 const struct security_info *info,
363 const void *data,
364 uint64_t *ret_badness,
365 char **ret_description) {
366
367 assert(ret_badness)do { if ((__builtin_expect(!!(!(ret_badness)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_badness"), "../src/analyze/analyze-security.c"
, 367, __PRETTY_FUNCTION__); } while (0)
;
368 assert(ret_description)do { if ((__builtin_expect(!!(!(ret_description)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_description"), "../src/analyze/analyze-security.c"
, 368, __PRETTY_FUNCTION__); } while (0)
;
369
370 *ret_badness = !streq_ptr(info->keyring_mode, "private");
371 *ret_description = NULL((void*)0);
372
373 return 0;
374}
375
376static int assess_notify_access(
377 const struct security_assessor *a,
378 const struct security_info *info,
379 const void *data,
380 uint64_t *ret_badness,
381 char **ret_description) {
382
383 assert(ret_badness)do { if ((__builtin_expect(!!(!(ret_badness)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_badness"), "../src/analyze/analyze-security.c"
, 383, __PRETTY_FUNCTION__); } while (0)
;
384 assert(ret_description)do { if ((__builtin_expect(!!(!(ret_description)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_description"), "../src/analyze/analyze-security.c"
, 384, __PRETTY_FUNCTION__); } while (0)
;
385
386 *ret_badness = streq_ptr(info->notify_access, "all");
387 *ret_description = NULL((void*)0);
388
389 return 0;
390}
391
392static int assess_remove_ipc(
393 const struct security_assessor *a,
394 const struct security_info *info,
395 const void *data,
396 uint64_t *ret_badness,
397 char **ret_description) {
398
399 assert(ret_badness)do { if ((__builtin_expect(!!(!(ret_badness)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_badness"), "../src/analyze/analyze-security.c"
, 399, __PRETTY_FUNCTION__); } while (0)
;
400 assert(ret_description)do { if ((__builtin_expect(!!(!(ret_description)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_description"), "../src/analyze/analyze-security.c"
, 400, __PRETTY_FUNCTION__); } while (0)
;
401
402 if (security_info_runs_privileged(info))
403 *ret_badness = UINT64_MAX(18446744073709551615UL);
404 else
405 *ret_badness = !info->remove_ipc;
406
407 *ret_description = NULL((void*)0);
408 return 0;
409}
410
411static int assess_supplementary_groups(
412 const struct security_assessor *a,
413 const struct security_info *info,
414 const void *data,
415 uint64_t *ret_badness,
416 char **ret_description) {
417
418 assert(ret_badness)do { if ((__builtin_expect(!!(!(ret_badness)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_badness"), "../src/analyze/analyze-security.c"
, 418, __PRETTY_FUNCTION__); } while (0)
;
419 assert(ret_description)do { if ((__builtin_expect(!!(!(ret_description)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_description"), "../src/analyze/analyze-security.c"
, 419, __PRETTY_FUNCTION__); } while (0)
;
420
421 if (security_info_runs_privileged(info))
422 *ret_badness = UINT64_MAX(18446744073709551615UL);
423 else
424 *ret_badness = !strv_isempty(info->supplementary_groups);
425
426 *ret_description = NULL((void*)0);
427 return 0;
428}
429
430static int assess_restrict_namespaces(
431 const struct security_assessor *a,
432 const struct security_info *info,
433 const void *data,
434 uint64_t *ret_badness,
435 char **ret_description) {
436
437 assert(ret_badness)do { if ((__builtin_expect(!!(!(ret_badness)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_badness"), "../src/analyze/analyze-security.c"
, 437, __PRETTY_FUNCTION__); } while (0)
;
438 assert(ret_description)do { if ((__builtin_expect(!!(!(ret_description)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_description"), "../src/analyze/analyze-security.c"
, 438, __PRETTY_FUNCTION__); } while (0)
;
439
440 *ret_badness = !!(info->restrict_namespaces & a->parameter);
441 *ret_description = NULL((void*)0);
442
443 return 0;
444}
445
446static int assess_system_call_architectures(
447 const struct security_assessor *a,
448 const struct security_info *info,
449 const void *data,
450 uint64_t *ret_badness,
451 char **ret_description) {
452
453 char *d;
454 uint64_t b;
455
456 assert(ret_badness)do { if ((__builtin_expect(!!(!(ret_badness)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_badness"), "../src/analyze/analyze-security.c"
, 456, __PRETTY_FUNCTION__); } while (0)
;
457 assert(ret_description)do { if ((__builtin_expect(!!(!(ret_description)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_description"), "../src/analyze/analyze-security.c"
, 457, __PRETTY_FUNCTION__); } while (0)
;
458
459 if (strv_isempty(info->system_call_architectures)) {
460 b = 10;
461 d = strdup("Service may execute system calls with all ABIs");
462 } else if (strv_equal(info->system_call_architectures, STRV_MAKE("native")((char**) ((const char*[]) { "native", ((void*)0) })))) {
463 b = 0;
464 d = strdup("Service may execute system calls only with native ABI");
465 } else {
466 b = 8;
467 d = strdup("Service may execute system calls with multiple ABIs");
468 }
469
470 if (!d)
471 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/analyze/analyze-security.c"
, 471, __func__)
;
472
473 *ret_badness = b;
474 *ret_description = d;
475
476 return 0;
477}
478
479static bool_Bool syscall_names_in_filter(Set *s, bool_Bool whitelist, const SyscallFilterSet *f) {
480 const char *syscall;
481
482 NULSTR_FOREACH(syscall, f->value)for ((syscall) = (f->value); (syscall) && *(syscall
); (syscall) = strchr((syscall), 0)+1)
{
483 bool_Bool b;
484
485 if (syscall[0] == '@') {
486 const SyscallFilterSet *g;
487 assert_se(g = syscall_filter_set_find(syscall))do { if ((__builtin_expect(!!(!(g = syscall_filter_set_find(syscall
))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("g = syscall_filter_set_find(syscall)"
), "../src/analyze/analyze-security.c", 487, __PRETTY_FUNCTION__
); } while (0)
;
488 b = syscall_names_in_filter(s, whitelist, g);
489 } else {
490#if HAVE_SECCOMP1
491 int id;
492
493 /* Let's see if the system call actually exists on this platform, before complaining */
494 id = seccomp_syscall_resolve_name(syscall);
495 if (id < 0)
496 continue;
497#endif
498
499 b = set_contains(s, syscall);
500 }
501
502 if (whitelist == b) {
503 log_debug("Offending syscall filter item: %s", syscall)({ 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/analyze/analyze-security.c", 503, __func__, "Offending syscall filter item: %s"
, syscall) : -abs(_e); })
;
504 return true1; /* bad! */
505 }
506 }
507
508 return false0;
509}
510
511static int assess_system_call_filter(
512 const struct security_assessor *a,
513 const struct security_info *info,
514 const void *data,
515 uint64_t *ret_badness,
516 char **ret_description) {
517
518 const SyscallFilterSet *f;
519 char *d = NULL((void*)0);
520 uint64_t b;
521
522 assert(a)do { if ((__builtin_expect(!!(!(a)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("a"), "../src/analyze/analyze-security.c"
, 522, __PRETTY_FUNCTION__); } while (0)
;
523 assert(info)do { if ((__builtin_expect(!!(!(info)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("info"), "../src/analyze/analyze-security.c"
, 523, __PRETTY_FUNCTION__); } while (0)
;
524 assert(ret_badness)do { if ((__builtin_expect(!!(!(ret_badness)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_badness"), "../src/analyze/analyze-security.c"
, 524, __PRETTY_FUNCTION__); } while (0)
;
525 assert(ret_description)do { if ((__builtin_expect(!!(!(ret_description)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_description"), "../src/analyze/analyze-security.c"
, 525, __PRETTY_FUNCTION__); } while (0)
;
526
527 assert(a->parameter < _SYSCALL_FILTER_SET_MAX)do { if ((__builtin_expect(!!(!(a->parameter < _SYSCALL_FILTER_SET_MAX
)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("a->parameter < _SYSCALL_FILTER_SET_MAX"
), "../src/analyze/analyze-security.c", 527, __PRETTY_FUNCTION__
); } while (0)
;
528 f = syscall_filter_sets + a->parameter;
529
530 if (!info->system_call_filter_whitelist && set_isempty(info->system_call_filter)) {
531 d = strdup("Service does not filter system calls");
532 b = 10;
533 } else {
534 bool_Bool bad;
535
536 log_debug("Analyzing system call filter, checking against: %s", f->name)({ 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/analyze/analyze-security.c", 536, __func__, "Analyzing system call filter, checking against: %s"
, f->name) : -abs(_e); })
;
537 bad = syscall_names_in_filter(info->system_call_filter, info->system_call_filter_whitelist, f);
538 log_debug("Result: %s", bad ? "bad" : "good")({ 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/analyze/analyze-security.c", 538, __func__, "Result: %s"
, bad ? "bad" : "good") : -abs(_e); })
;
539
540 if (info->system_call_filter_whitelist) {
541 if (bad) {
542 (void) asprintf(&d, "System call whitelist defined for service, and %s is included", f->name);
543 b = 9;
544 } else {
545 (void) asprintf(&d, "System call whitelist defined for service, and %s is not included", f->name);
546 b = 0;
547 }
548 } else {
549 if (bad) {
550 (void) asprintf(&d, "System call blacklist defined for service, and %s is not included", f->name);
551 b = 10;
552 } else {
553 (void) asprintf(&d, "System call blacklist defined for service, and %s is included", f->name);
554 b = 5;
555 }
556 }
557 }
558
559 if (!d)
560 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/analyze/analyze-security.c"
, 560, __func__)
;
561
562 *ret_badness = b;
563 *ret_description = d;
564
565 return 0;
566}
567
568static int assess_ip_address_allow(
569 const struct security_assessor *a,
570 const struct security_info *info,
571 const void *data,
572 uint64_t *ret_badness,
573 char **ret_description) {
574
575 char *d = NULL((void*)0);
576 uint64_t b;
577
578 assert(info)do { if ((__builtin_expect(!!(!(info)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("info"), "../src/analyze/analyze-security.c"
, 578, __PRETTY_FUNCTION__); } while (0)
;
579 assert(ret_badness)do { if ((__builtin_expect(!!(!(ret_badness)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_badness"), "../src/analyze/analyze-security.c"
, 579, __PRETTY_FUNCTION__); } while (0)
;
580 assert(ret_description)do { if ((__builtin_expect(!!(!(ret_description)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_description"), "../src/analyze/analyze-security.c"
, 580, __PRETTY_FUNCTION__); } while (0)
;
581
582 if (!info->ip_address_deny_all) {
583 d = strdup("Service does not define an IP address whitelist");
584 b = 10;
585 } else if (info->ip_address_allow_other) {
586 d = strdup("Service defines IP address whitelist with non-localhost entries");
587 b = 5;
588 } else if (info->ip_address_allow_localhost) {
589 d = strdup("Service defines IP address whitelits with only localhost entries");
590 b = 2;
591 } else {
592 d = strdup("Service blocks all IP address ranges");
593 b = 0;
594 }
595
596 if (!d)
597 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/analyze/analyze-security.c"
, 597, __func__)
;
598
599 *ret_badness = b;
600 *ret_description = d;
601
602 return 0;
603}
604
605static int assess_device_allow(
606 const struct security_assessor *a,
607 const struct security_info *info,
608 const void *data,
609 uint64_t *ret_badness,
610 char **ret_description) {
611
612 char *d = NULL((void*)0);
613 uint64_t b;
614
615 assert(info)do { if ((__builtin_expect(!!(!(info)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("info"), "../src/analyze/analyze-security.c"
, 615, __PRETTY_FUNCTION__); } while (0)
;
616 assert(ret_badness)do { if ((__builtin_expect(!!(!(ret_badness)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_badness"), "../src/analyze/analyze-security.c"
, 616, __PRETTY_FUNCTION__); } while (0)
;
617 assert(ret_description)do { if ((__builtin_expect(!!(!(ret_description)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_description"), "../src/analyze/analyze-security.c"
, 617, __PRETTY_FUNCTION__); } while (0)
;
618
619 if (STRPTR_IN_SET(info->device_policy, "strict", "closed")({ const char* _x = (info->device_policy); _x && (
!!strv_find((((char**) ((const char*[]) { "strict", "closed",
((void*)0) }))), (_x))); })
) {
620
621 if (info->device_allow_non_empty) {
622 d = strdup("Service has a device ACL with some special devices");
623 b = 5;
624 } else {
625 d = strdup("Service has a minimal device ACL");
626 b = 0;
627 }
628 } else {
629 d = strdup("Service has no device ACL");
630 b = 10;
631 }
632
633 if (!d)
634 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/analyze/analyze-security.c"
, 634, __func__)
;
635
636 *ret_badness = b;
637 *ret_description = d;
638
639 return 0;
640}
641
642static int assess_ambient_capabilities(
643 const struct security_assessor *a,
644 const struct security_info *info,
645 const void *data,
646 uint64_t *ret_badness,
647 char **ret_description) {
648
649 assert(ret_badness)do { if ((__builtin_expect(!!(!(ret_badness)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_badness"), "../src/analyze/analyze-security.c"
, 649, __PRETTY_FUNCTION__); } while (0)
;
650 assert(ret_description)do { if ((__builtin_expect(!!(!(ret_description)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("ret_description"), "../src/analyze/analyze-security.c"
, 650, __PRETTY_FUNCTION__); } while (0)
;
651
652 *ret_badness = info->ambient_capabilities != 0;
653 *ret_description = NULL((void*)0);
654
655 return 0;
656}
657
658static const struct security_assessor security_assessor_table[] = {
659 {
660 .id = "User=/DynamicUser=",
661 .description_bad = "Service runs as root user",
662 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#User=",
663 .weight = 2000,
664 .range = 10,
665 .assess = assess_user,
666 },
667 {
668 .id = "SupplementaryGroups=",
669 .description_good = "Service has no supplementary groups",
670 .description_bad = "Service runs with supplementary groups",
671 .description_na = "Service runs as root, option does not matter",
672 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SupplementaryGroups=",
673 .weight = 200,
674 .range = 1,
675 .assess = assess_supplementary_groups,
676 },
677 {
678 .id = "PrivateDevices=",
679 .description_good = "Service has no access to hardware devices",
680 .description_bad = "Service potentially has access to hardware devices",
681 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateDevices=",
682 .weight = 1000,
683 .range = 1,
684 .assess = assess_bool,
685 .offset = offsetof(struct security_info, private_devices)__builtin_offsetof(struct security_info, private_devices),
686 },
687 {
688 .id = "PrivateMounts=",
689 .description_good = "Service cannot install system mounts",
690 .description_bad = "Service may install system mounts",
691 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateMounts=",
692 .weight = 1000,
693 .range = 1,
694 .assess = assess_bool,
695 .offset = offsetof(struct security_info, private_mounts)__builtin_offsetof(struct security_info, private_mounts),
696 },
697 {
698 .id = "PrivateNetwork=",
699 .description_good = "Service has no access to the host's network",
700 .description_bad = "Service has access to the host's network",
701 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateNetwork=",
702 .weight = 2500,
703 .range = 1,
704 .assess = assess_bool,
705 .offset = offsetof(struct security_info, private_network)__builtin_offsetof(struct security_info, private_network),
706 },
707 {
708 .id = "PrivateTmp=",
709 .description_good = "Service has no access to other software's temporary files",
710 .description_bad = "Service has access to other software's temporary files",
711 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateTmp=",
712 .weight = 1000,
713 .range = 1,
714 .assess = assess_bool,
715 .offset = offsetof(struct security_info, private_tmp)__builtin_offsetof(struct security_info, private_tmp),
716 .default_dependencies_only = true1,
717 },
718 {
719 .id = "PrivateUsers=",
720 .description_good = "Service does not have access to other users",
721 .description_bad = "Service has access to other users",
722 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateUsers=",
723 .weight = 1000,
724 .range = 1,
725 .assess = assess_bool,
726 .offset = offsetof(struct security_info, private_users)__builtin_offsetof(struct security_info, private_users),
727 },
728 {
729 .id = "ProtectControlGroups=",
730 .description_good = "Service cannot modify the control group file system",
731 .description_bad = "Service may modify to the control group file system",
732 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectControlGroups=",
733 .weight = 1000,
734 .range = 1,
735 .assess = assess_bool,
736 .offset = offsetof(struct security_info, protect_control_groups)__builtin_offsetof(struct security_info, protect_control_groups
)
,
737 },
738 {
739 .id = "ProtectKernelModules=",
740 .description_good = "Service cannot load or read kernel modules",
741 .description_bad = "Service may load or read kernel modules",
742 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectKernelModules=",
743 .weight = 1000,
744 .range = 1,
745 .assess = assess_bool,
746 .offset = offsetof(struct security_info, protect_kernel_modules)__builtin_offsetof(struct security_info, protect_kernel_modules
)
,
747 },
748 {
749 .id = "ProtectKernelTunables=",
750 .description_good = "Service cannot alter kernel tunables (/proc/sys, …)",
751 .description_bad = "Service may alter kernel tunables",
752 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectKernelTunables=",
753 .weight = 1000,
754 .range = 1,
755 .assess = assess_bool,
756 .offset = offsetof(struct security_info, protect_kernel_tunables)__builtin_offsetof(struct security_info, protect_kernel_tunables
)
,
757 },
758 {
759 .id = "ProtectHome=",
760 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectHome=",
761 .weight = 1000,
762 .range = 10,
763 .assess = assess_protect_home,
764 .default_dependencies_only = true1,
765 },
766 {
767 .id = "ProtectSystem=",
768 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectSystem=",
769 .weight = 1000,
770 .range = 10,
771 .assess = assess_protect_system,
772 .default_dependencies_only = true1,
773 },
774 {
775 .id = "RootDirectory=/RootImage=",
776 .description_good = "Service has its own root directory/image",
777 .description_bad = "Service runs within the host's root directory",
778 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RootDirectory=",
779 .weight = 200,
780 .range = 1,
781 .assess = assess_root_directory,
782 .default_dependencies_only = true1,
783 },
784 {
785 .id = "LockPersonality=",
786 .description_good = "Service cannot change ABI personality",
787 .description_bad = "Service may change ABI personality",
788 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#LockPersonality=",
789 .weight = 100,
790 .range = 1,
791 .assess = assess_bool,
792 .offset = offsetof(struct security_info, lock_personality)__builtin_offsetof(struct security_info, lock_personality),
793 },
794 {
795 .id = "MemoryDenyWriteExecute=",
796 .description_good = "Service cannot create writable executable memory mappings",
797 .description_bad = "Service may create writable executable memory mappings",
798 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#MemoryDenyWriteExecute=",
799 .weight = 100,
800 .range = 1,
801 .assess = assess_bool,
802 .offset = offsetof(struct security_info, memory_deny_write_execute)__builtin_offsetof(struct security_info, memory_deny_write_execute
)
,
803 },
804 {
805 .id = "NoNewPrivileges=",
806 .description_good = "Service processes cannot acquire new privileges",
807 .description_bad = "Service processes may acquire new privileges",
808 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#NoNewPrivileges=",
809 .weight = 1000,
810 .range = 1,
811 .assess = assess_bool,
812 .offset = offsetof(struct security_info, no_new_privileges)__builtin_offsetof(struct security_info, no_new_privileges),
813 },
814 {
815 .id = "CapabilityBoundingSet=~CAP_SYS_ADMIN",
816 .description_good = "Service has no administrator privileges",
817 .description_bad = "Service has administrator privileges",
818 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
819 .weight = 1500,
820 .range = 1,
821 .assess = assess_capability_bounding_set,
822 .parameter = UINT64_C(1)1UL << CAP_SYS_ADMIN21,
823 },
824 {
825 .id = "CapabilityBoundingSet=~CAP_SET(UID|GID|PCAP)",
826 .description_good = "Service cannot change UID/GID identities/capabilities",
827 .description_bad = "Service may change UID/GID identities/capabilities",
828 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
829 .weight = 1500,
830 .range = 1,
831 .assess = assess_capability_bounding_set,
832 .parameter = (UINT64_C(1)1UL << CAP_SETUID7)|
833 (UINT64_C(1)1UL << CAP_SETGID6)|
834 (UINT64_C(1)1UL << CAP_SETPCAP8),
835 },
836 {
837 .id = "CapabilityBoundingSet=~CAP_SYS_PTRACE",
838 .description_good = "Service has no ptrace() debugging abilities",
839 .description_bad = "Service has ptrace() debugging abilities",
840 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
841 .weight = 1500,
842 .range = 1,
843 .assess = assess_capability_bounding_set,
844 .parameter = (UINT64_C(1)1UL << CAP_SYS_PTRACE19),
845 },
846 {
847 .id = "CapabilityBoundingSet=~CAP_SYS_TIME",
848 .description_good = "Service processes cannot change the system clock",
849 .description_bad = "Service processes may change the system clock",
850 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
851 .weight = 1000,
852 .range = 1,
853 .assess = assess_capability_bounding_set,
854 .parameter = UINT64_C(1)1UL << CAP_SYS_TIME25,
855 },
856 {
857 .id = "CapabilityBoundingSet=~CAP_NET_ADMIN",
858 .description_good = "Service has no network configuration privileges",
859 .description_bad = "Service has network configuration privileges",
860 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
861 .weight = 1000,
862 .range = 1,
863 .assess = assess_capability_bounding_set,
864 .parameter = (UINT64_C(1)1UL << CAP_NET_ADMIN12),
865 },
866 {
867 .id = "CapabilityBoundingSet=~CAP_RAWIO",
868 .description_good = "Service has no raw I/O access",
869 .description_bad = "Service has raw I/O access",
870 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
871 .weight = 1000,
872 .range = 1,
873 .assess = assess_capability_bounding_set,
874 .parameter = (UINT64_C(1)1UL << CAP_SYS_RAWIO17),
875 },
876 {
877 .id = "CapabilityBoundingSet=~CAP_SYS_MODULE",
878 .description_good = "Service cannot load kernel modules",
879 .description_bad = "Service may load kernel modules",
880 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
881 .weight = 1000,
882 .range = 1,
883 .assess = assess_capability_bounding_set,
884 .parameter = (UINT64_C(1)1UL << CAP_SYS_MODULE16),
885 },
886 {
887 .id = "CapabilityBoundingSet=~CAP_AUDIT_*",
888 .description_good = "Service has no audit subsystem access",
889 .description_bad = "Service has audit subsystem access",
890 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
891 .weight = 500,
892 .range = 1,
893 .assess = assess_capability_bounding_set,
894 .parameter = (UINT64_C(1)1UL << CAP_AUDIT_CONTROL30) |
895 (UINT64_C(1)1UL << CAP_AUDIT_READ37) |
896 (UINT64_C(1)1UL << CAP_AUDIT_WRITE29),
897 },
898 {
899 .id = "CapabilityBoundingSet=~CAP_SYSLOG",
900 .description_good = "Service has no access to kernel logging",
901 .description_bad = "Service has access to kernel logging",
902 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
903 .weight = 500,
904 .range = 1,
905 .assess = assess_capability_bounding_set,
906 .parameter = (UINT64_C(1)1UL << CAP_SYSLOG34),
907 },
908 {
909 .id = "CapabilityBoundingSet=~CAP_SYS_(NICE|RESOURCE)",
910 .description_good = "Service has no privileges to change resource use parameters",
911 .description_bad = "Service has privileges to change resource use parameters",
912 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
913 .weight = 500,
914 .range = 1,
915 .assess = assess_capability_bounding_set,
916 .parameter = (UINT64_C(1)1UL << CAP_SYS_NICE23) |
917 (UINT64_C(1)1UL << CAP_SYS_RESOURCE24),
918 },
919 {
920 .id = "CapabilityBoundingSet=~CAP_MKNOD",
921 .description_good = "Service cannot create device nodes",
922 .description_bad = "Service may create device nodes",
923 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
924 .weight = 500,
925 .range = 1,
926 .assess = assess_capability_bounding_set,
927 .parameter = (UINT64_C(1)1UL << CAP_MKNOD27),
928 },
929 {
930 .id = "CapabilityBoundingSet=~CAP_(CHOWN|FSETID|SETFCAP)",
931 .description_good = "Service cannot change file ownership/access mode/capabilities",
932 .description_bad = "Service may change file ownership/access mode/capabilities unrestricted",
933 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
934 .weight = 1000,
935 .range = 1,
936 .assess = assess_capability_bounding_set,
937 .parameter = (UINT64_C(1)1UL << CAP_CHOWN0) |
938 (UINT64_C(1)1UL << CAP_FSETID4) |
939 (UINT64_C(1)1UL << CAP_SETFCAP31),
940 },
941 {
942 .id = "CapabilityBoundingSet=~CAP_(DAC_*|FOWNER|IPC_OWNER)",
943 .description_good = "Service cannot override UNIX file/IPC permission checks",
944 .description_bad = "Service may override UNIX file/IPC permission checks",
945 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
946 .weight = 1000,
947 .range = 1,
948 .assess = assess_capability_bounding_set,
949 .parameter = (UINT64_C(1)1UL << CAP_DAC_OVERRIDE1) |
950 (UINT64_C(1)1UL << CAP_DAC_READ_SEARCH2) |
951 (UINT64_C(1)1UL << CAP_FOWNER3) |
952 (UINT64_C(1)1UL << CAP_IPC_OWNER15),
953 },
954 {
955 .id = "CapabilityBoundingSet=~CAP_KILL",
956 .description_good = "Service cannot send UNIX signals to arbitrary processes",
957 .description_bad = "Service may send UNIX signals to arbitrary processes",
958 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
959 .weight = 500,
960 .range = 1,
961 .assess = assess_capability_bounding_set,
962 .parameter = (UINT64_C(1)1UL << CAP_KILL5),
963 },
964 {
965 .id = "CapabilityBoundingSet=~CAP_NET_(BIND_SERVICE|BROADCAST|RAW)",
966 .description_good = "Service has no elevated networking privileges",
967 .description_bad = "Service has elevated networking privileges",
968 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
969 .weight = 500,
970 .range = 1,
971 .assess = assess_capability_bounding_set,
972 .parameter = (UINT64_C(1)1UL << CAP_NET_BIND_SERVICE10) |
973 (UINT64_C(1)1UL << CAP_NET_BROADCAST11) |
974 (UINT64_C(1)1UL << CAP_NET_RAW13),
975 },
976 {
977 .id = "CapabilityBoundingSet=~CAP_SYS_BOOT",
978 .description_good = "Service cannot issue reboot()",
979 .description_bad = "Service may issue reboot()",
980 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
981 .weight = 100,
982 .range = 1,
983 .assess = assess_capability_bounding_set,
984 .parameter = (UINT64_C(1)1UL << CAP_SYS_BOOT22),
985 },
986 {
987 .id = "CapabilityBoundingSet=~CAP_MAC_*",
988 .description_good = "Service cannot adjust SMACK MAC",
989 .description_bad = "Service may adjust SMACK MAC",
990 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
991 .weight = 100,
992 .range = 1,
993 .assess = assess_capability_bounding_set,
994 .parameter = (UINT64_C(1)1UL << CAP_MAC_ADMIN33)|
995 (UINT64_C(1)1UL << CAP_MAC_OVERRIDE32),
996 },
997 {
998 .id = "CapabilityBoundingSet=~CAP_LINUX_IMMUTABLE",
999 .description_good = "Service cannot mark files immutable",
1000 .description_bad = "Service may mark files immutable",
1001 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
1002 .weight = 75,
1003 .range = 1,
1004 .assess = assess_capability_bounding_set,
1005 .parameter = (UINT64_C(1)1UL << CAP_LINUX_IMMUTABLE9),
1006 },
1007 {
1008 .id = "CapabilityBoundingSet=~CAP_IPC_LOCK",
1009 .description_good = "Service cannot lock memory into RAM",
1010 .description_bad = "Service may lock memory into RAM",
1011 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
1012 .weight = 50,
1013 .range = 1,
1014 .assess = assess_capability_bounding_set,
1015 .parameter = (UINT64_C(1)1UL << CAP_IPC_LOCK14),
1016 },
1017 {
1018 .id = "CapabilityBoundingSet=~CAP_SYS_CHROOT",
1019 .description_good = "Service cannot issue chroot()",
1020 .description_bad = "Service may issue chroot()",
1021 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
1022 .weight = 50,
1023 .range = 1,
1024 .assess = assess_capability_bounding_set,
1025 .parameter = (UINT64_C(1)1UL << CAP_SYS_CHROOT18),
1026 },
1027 {
1028 .id = "CapabilityBoundingSet=~CAP_BLOCK_SUSPEND",
1029 .description_good = "Service cannot establish wake locks",
1030 .description_bad = "Service may establish wake locks",
1031 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
1032 .weight = 25,
1033 .range = 1,
1034 .assess = assess_capability_bounding_set,
1035 .parameter = (UINT64_C(1)1UL << CAP_BLOCK_SUSPEND36),
1036 },
1037 {
1038 .id = "CapabilityBoundingSet=~CAP_WAKE_ALARM",
1039 .description_good = "Service cannot program timers that wake up the system",
1040 .description_bad = "Service may program timers that wake up the system",
1041 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
1042 .weight = 25,
1043 .range = 1,
1044 .assess = assess_capability_bounding_set,
1045 .parameter = (UINT64_C(1)1UL << CAP_WAKE_ALARM35),
1046 },
1047 {
1048 .id = "CapabilityBoundingSet=~CAP_LEASE",
1049 .description_good = "Service cannot create file leases",
1050 .description_bad = "Service may create file leases",
1051 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
1052 .weight = 25,
1053 .range = 1,
1054 .assess = assess_capability_bounding_set,
1055 .parameter = (UINT64_C(1)1UL << CAP_LEASE28),
1056 },
1057 {
1058 .id = "CapabilityBoundingSet=~CAP_SYS_TTY_CONFIG",
1059 .description_good = "Service cannot issue vhangup()",
1060 .description_bad = "Service may issue vhangup()",
1061 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
1062 .weight = 25,
1063 .range = 1,
1064 .assess = assess_capability_bounding_set,
1065 .parameter = (UINT64_C(1)1UL << CAP_SYS_TTY_CONFIG26),
1066 },
1067 {
1068 .id = "CapabilityBoundingSet=~CAP_SYS_PACCT",
1069 .description_good = "Service cannot use acct()",
1070 .description_bad = "Service may use acct()",
1071 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
1072 .weight = 25,
1073 .range = 1,
1074 .assess = assess_capability_bounding_set,
1075 .parameter = (UINT64_C(1)1UL << CAP_SYS_PACCT20),
1076 },
1077 {
1078 .id = "UMask=",
1079 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#UMask=",
1080 .weight = 100,
1081 .range = 10,
1082 .assess = assess_umask,
1083 },
1084 {
1085 .id = "KeyringMode=",
1086 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#KeyringMode=",
1087 .description_good = "Service doesn't share key material with other services",
1088 .description_bad = "Service shares key material with other service",
1089 .weight = 1000,
1090 .range = 1,
1091 .assess = assess_keyring_mode,
1092 },
1093 {
1094 .id = "NotifyAccess=",
1095 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#NotifyAccess=",
1096 .description_good = "Service child processes cannot alter service state",
1097 .description_bad = "Service child processes may alter service state",
1098 .weight = 1000,
1099 .range = 1,
1100 .assess = assess_notify_access,
1101 },
1102 {
1103 .id = "RemoveIPC=",
1104 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RemoveIPC=",
1105 .description_good = "Service user cannot leave SysV IPC objects around",
1106 .description_bad = "Service user may leave SysV IPC objects around",
1107 .description_na = "Service runs as root, option does not apply",
1108 .weight = 100,
1109 .range = 1,
1110 .assess = assess_remove_ipc,
1111 .offset = offsetof(struct security_info, remove_ipc)__builtin_offsetof(struct security_info, remove_ipc),
1112 },
1113 {
1114 .id = "Delegate=",
1115 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Delegate=",
1116 .description_good = "Service does not maintain its own delegated control group subtree",
1117 .description_bad = "Service maintains its own delegated control group subtree",
1118 .weight = 100,
1119 .range = 1,
1120 .assess = assess_bool,
1121 .offset = offsetof(struct security_info, delegate)__builtin_offsetof(struct security_info, delegate),
1122 .parameter = true1, /* invert! */
1123 },
1124 {
1125 .id = "RestrictRealtime=",
1126 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictRealtime=",
1127 .description_good = "Service realtime scheduling access is restricted",
1128 .description_bad = "Service may acquire realtime scheduling",
1129 .weight = 500,
1130 .range = 1,
1131 .assess = assess_bool,
1132 .offset = offsetof(struct security_info, restrict_realtime)__builtin_offsetof(struct security_info, restrict_realtime),
1133 },
1134 {
1135 .id = "RestrictSUIDSGID=",
1136 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictSUIDSGID=",
1137 .description_good = "SUID/SGID file creation by service is restricted",
1138 .description_bad = "Service may create SUID/SGID files",
1139 .weight = 1000,
1140 .range = 1,
1141 .assess = assess_bool,
1142 .offset = offsetof(struct security_info, restrict_suid_sgid)__builtin_offsetof(struct security_info, restrict_suid_sgid),
1143 },
1144 {
1145 .id = "RestrictNamespaces=~CLONE_NEWUSER",
1146 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
1147 .description_good = "Service cannot create user namespaces",
1148 .description_bad = "Service may create user namespaces",
1149 .weight = 1500,
1150 .range = 1,
1151 .assess = assess_restrict_namespaces,
1152 .parameter = CLONE_NEWUSER0x10000000,
1153 },
1154 {
1155 .id = "RestrictNamespaces=~CLONE_NEWNS",
1156 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
1157 .description_good = "Service cannot create file system namespaces",
1158 .description_bad = "Service may create file system namespaces",
1159 .weight = 500,
1160 .range = 1,
1161 .assess = assess_restrict_namespaces,
1162 .parameter = CLONE_NEWNS0x00020000,
1163 },
1164 {
1165 .id = "RestrictNamespaces=~CLONE_NEWIPC",
1166 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
1167 .description_good = "Service cannot create IPC namespaces",
1168 .description_bad = "Service may create IPC namespaces",
1169 .weight = 500,
1170 .range = 1,
1171 .assess = assess_restrict_namespaces,
1172 .parameter = CLONE_NEWIPC0x08000000,
1173 },
1174 {
1175 .id = "RestrictNamespaces=~CLONE_NEWPID",
1176 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
1177 .description_good = "Service cannot create process namespaces",
1178 .description_bad = "Service may create process namespaces",
1179 .weight = 500,
1180 .range = 1,
1181 .assess = assess_restrict_namespaces,
1182 .parameter = CLONE_NEWPID0x20000000,
1183 },
1184 {
1185 .id = "RestrictNamespaces=~CLONE_NEWCGROUP",
1186 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
1187 .description_good = "Service cannot create cgroup namespaces",
1188 .description_bad = "Service may create cgroup namespaces",
1189 .weight = 500,
1190 .range = 1,
1191 .assess = assess_restrict_namespaces,
1192 .parameter = CLONE_NEWCGROUP0x02000000,
1193 },
1194 {
1195 .id = "RestrictNamespaces=~CLONE_NEWNET",
1196 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
1197 .description_good = "Service cannot create network namespaces",
1198 .description_bad = "Service may create network namespaces",
1199 .weight = 500,
1200 .range = 1,
1201 .assess = assess_restrict_namespaces,
1202 .parameter = CLONE_NEWNET0x40000000,
1203 },
1204 {
1205 .id = "RestrictNamespaces=~CLONE_NEWUTS",
1206 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
1207 .description_good = "Service cannot create hostname namespaces",
1208 .description_bad = "Service may create hostname namespaces",
1209 .weight = 100,
1210 .range = 1,
1211 .assess = assess_restrict_namespaces,
1212 .parameter = CLONE_NEWUTS0x04000000,
1213 },
1214 {
1215 .id = "RestrictAddressFamilies=~AF_(INET|INET6)",
1216 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=",
1217 .description_good = "Service cannot allocate Internet sockets",
1218 .description_bad = "Service may allocate Internet sockets",
1219 .weight = 1500,
1220 .range = 1,
1221 .assess = assess_bool,
1222 .offset = offsetof(struct security_info, restrict_address_family_inet)__builtin_offsetof(struct security_info, restrict_address_family_inet
)
,
1223 },
1224 {
1225 .id = "RestrictAddressFamilies=~AF_UNIX",
1226 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=",
1227 .description_good = "Service cannot allocate local sockets",
1228 .description_bad = "Service may allocate local sockets",
1229 .weight = 25,
1230 .range = 1,
1231 .assess = assess_bool,
1232 .offset = offsetof(struct security_info, restrict_address_family_unix)__builtin_offsetof(struct security_info, restrict_address_family_unix
)
,
1233 },
1234 {
1235 .id = "RestrictAddressFamilies=~AF_NETLINK",
1236 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=",
1237 .description_good = "Service cannot allocate netlink sockets",
1238 .description_bad = "Service may allocate netlink sockets",
1239 .weight = 200,
1240 .range = 1,
1241 .assess = assess_bool,
1242 .offset = offsetof(struct security_info, restrict_address_family_netlink)__builtin_offsetof(struct security_info, restrict_address_family_netlink
)
,
1243 },
1244 {
1245 .id = "RestrictAddressFamilies=~AF_PACKET",
1246 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=",
1247 .description_good = "Service cannot allocate packet sockets",
1248 .description_bad = "Service may allocate packet sockets",
1249 .weight = 1000,
1250 .range = 1,
1251 .assess = assess_bool,
1252 .offset = offsetof(struct security_info, restrict_address_family_packet)__builtin_offsetof(struct security_info, restrict_address_family_packet
)
,
1253 },
1254 {
1255 .id = "RestrictAddressFamilies=~…",
1256 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=",
1257 .description_good = "Service cannot allocate exotic sockets",
1258 .description_bad = "Service may allocate exotic sockets",
1259 .weight = 1250,
1260 .range = 1,
1261 .assess = assess_bool,
1262 .offset = offsetof(struct security_info, restrict_address_family_other)__builtin_offsetof(struct security_info, restrict_address_family_other
)
,
1263 },
1264 {
1265 .id = "SystemCallArchitectures=",
1266 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallArchitectures=",
1267 .weight = 1000,
1268 .range = 10,
1269 .assess = assess_system_call_architectures,
1270 },
1271 {
1272 .id = "SystemCallFilter=~@swap",
1273 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
1274 .weight = 1000,
1275 .range = 10,
1276 .assess = assess_system_call_filter,
1277 .parameter = SYSCALL_FILTER_SET_SWAP,
1278 },
1279 {
1280 .id = "SystemCallFilter=~@obsolete",
1281 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
1282 .weight = 250,
1283 .range = 10,
1284 .assess = assess_system_call_filter,
1285 .parameter = SYSCALL_FILTER_SET_OBSOLETE,
1286 },
1287 {
1288 .id = "SystemCallFilter=~@clock",
1289 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
1290 .weight = 1000,
1291 .range = 10,
1292 .assess = assess_system_call_filter,
1293 .parameter = SYSCALL_FILTER_SET_CLOCK,
1294 },
1295 {
1296 .id = "SystemCallFilter=~@cpu-emulation",
1297 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
1298 .weight = 250,
1299 .range = 10,
1300 .assess = assess_system_call_filter,
1301 .parameter = SYSCALL_FILTER_SET_CPU_EMULATION,
1302 },
1303 {
1304 .id = "SystemCallFilter=~@debug",
1305 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
1306 .weight = 1000,
1307 .range = 10,
1308 .assess = assess_system_call_filter,
1309 .parameter = SYSCALL_FILTER_SET_DEBUG,
1310 },
1311 {
1312 .id = "SystemCallFilter=~@mount",
1313 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
1314 .weight = 1000,
1315 .range = 10,
1316 .assess = assess_system_call_filter,
1317 .parameter = SYSCALL_FILTER_SET_MOUNT,
1318 },
1319 {
1320 .id = "SystemCallFilter=~@module",
1321 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
1322 .weight = 1000,
1323 .range = 10,
1324 .assess = assess_system_call_filter,
1325 .parameter = SYSCALL_FILTER_SET_MODULE,
1326 },
1327 {
1328 .id = "SystemCallFilter=~@raw-io",
1329 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
1330 .weight = 1000,
1331 .range = 10,
1332 .assess = assess_system_call_filter,
1333 .parameter = SYSCALL_FILTER_SET_RAW_IO,
1334 },
1335 {
1336 .id = "SystemCallFilter=~@reboot",
1337 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
1338 .weight = 1000,
1339 .range = 10,
1340 .assess = assess_system_call_filter,
1341 .parameter = SYSCALL_FILTER_SET_REBOOT,
1342 },
1343 {
1344 .id = "SystemCallFilter=~@privileged",
1345 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
1346 .weight = 700,
1347 .range = 10,
1348 .assess = assess_system_call_filter,
1349 .parameter = SYSCALL_FILTER_SET_PRIVILEGED,
1350 },
1351 {
1352 .id = "SystemCallFilter=~@resources",
1353 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
1354 .weight = 700,
1355 .range = 10,
1356 .assess = assess_system_call_filter,
1357 .parameter = SYSCALL_FILTER_SET_RESOURCES,
1358 },
1359 {
1360 .id = "IPAddressDeny=",
1361 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#IPAddressDeny=",
1362 .weight = 1000,
1363 .range = 10,
1364 .assess = assess_ip_address_allow,
1365 },
1366 {
1367 .id = "DeviceAllow=",
1368 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#DeviceAllow=",
1369 .weight = 1000,
1370 .range = 10,
1371 .assess = assess_device_allow,
1372 },
1373 {
1374 .id = "AmbientCapabilities=",
1375 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#AmbientCapabilities=",
1376 .description_good = "Service process does not receive ambient capabilities",
1377 .description_bad = "Service process receives ambient capabilities",
1378 .weight = 500,
1379 .range = 1,
1380 .assess = assess_ambient_capabilities,
1381 },
1382};
1383
1384static int assess(const struct security_info *info, Table *overview_table, AnalyzeSecurityFlags flags) {
1385 static const struct {
1386 uint64_t exposure;
1387 const char *name;
1388 const char *color;
1389 SpecialGlyph smiley;
1390 } badness_table[] = {
1391 { 100, "DANGEROUS", ANSI_HIGHLIGHT_RED"\x1B[0;1;31m", DEPRESSED_SMILEY },
1392 { 90, "UNSAFE", ANSI_HIGHLIGHT_RED"\x1B[0;1;31m", UNHAPPY_SMILEY },
1393 { 75, "EXPOSED", ANSI_HIGHLIGHT_YELLOW"\x1B[0;1;33m", SLIGHTLY_UNHAPPY_SMILEY },
1394 { 50, "MEDIUM", NULL((void*)0), NEUTRAL_SMILEY },
1395 { 10, "OK", ANSI_HIGHLIGHT_GREEN"\x1B[0;1;32m", SLIGHTLY_HAPPY_SMILEY },
1396 { 1, "SAFE", ANSI_HIGHLIGHT_GREEN"\x1B[0;1;32m", HAPPY_SMILEY },
1397 { 0, "PERFECT", ANSI_HIGHLIGHT_GREEN"\x1B[0;1;32m", ECSTATIC_SMILEY },
1398 };
1399
1400 uint64_t badness_sum = 0, weight_sum = 0, exposure;
1401 _cleanup_(table_unrefp)__attribute__((cleanup(table_unrefp))) Table *details_table = NULL((void*)0);
1402 size_t i;
1403 int r;
1404
1405 if (!FLAGS_SET(flags, ANALYZE_SECURITY_SHORT)(((flags) & (ANALYZE_SECURITY_SHORT)) == (ANALYZE_SECURITY_SHORT
))
) {
1
Assuming the condition is true
2
Taking false branch
1406 details_table = table_new("", "NAME", "DESCRIPTION", "WEIGHT", "BADNESS", "RANGE", "EXPOSURE")table_new_internal("", "NAME", "DESCRIPTION", "WEIGHT", "BADNESS"
, "RANGE", "EXPOSURE", ((void*)0))
;
1407 if (!details_table)
1408 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/analyze/analyze-security.c"
, 1408, __func__)
;
1409
1410 (void) table_set_sort(details_table, 3, 1, (size_t) -1);
1411 (void) table_set_reverse(details_table, 3, true1);
1412
1413 if (getenv_bool("SYSTEMD_ANALYZE_DEBUG") <= 0)
1414 (void) table_set_display(details_table, 0, 1, 2, 6, (size_t) -1);
1415 }
1416
1417 for (i = 0; i < ELEMENTSOF(security_assessor_table)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(security_assessor_table), typeof(&*(security_assessor_table
))), sizeof(security_assessor_table)/sizeof((security_assessor_table
)[0]), ((void)0)))
; i++) {
3
Loop condition is true. Entering loop body
15
Potential leak of memory pointed to by 'd'
1418 const struct security_assessor *a = security_assessor_table + i;
1419 _cleanup_free___attribute__((cleanup(freep))) char *d = NULL((void*)0);
1420 uint64_t badness;
1421 void *data;
1422
1423 data = (uint8_t*) info + a->offset;
1424
1425 if (a->default_dependencies_only && !info->default_dependencies) {
4
Assuming field 'default_dependencies_only' is true
5
Assuming field 'default_dependencies' is false
6
Taking true branch
1426 badness = UINT64_MAX(18446744073709551615UL);
1427 d = strdup("Service runs in special boot phase, option does not apply");
7
Memory is allocated
1428 if (!d)
8
Assuming 'd' is non-null
9
Taking false branch
1429 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/analyze/analyze-security.c"
, 1429, __func__)
;
1430 } else {
1431 r = a->assess(a, info, data, &badness, &d);
1432 if (r < 0)
1433 return r;
1434 }
1435
1436 assert(a->range > 0)do { if ((__builtin_expect(!!(!(a->range > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("a->range > 0"), "../src/analyze/analyze-security.c"
, 1436, __PRETTY_FUNCTION__); } while (0)
;
10
Assuming field 'range' is > 0
11
Taking false branch
12
Loop condition is false. Exiting loop
1437
1438 if (badness
12.1
'badness' is equal to UINT64_MAX
!= UINT64_MAX(18446744073709551615UL)) {
13
Taking false branch
1439 assert(badness <= a->range)do { if ((__builtin_expect(!!(!(badness <= a->range)),0
))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("badness <= a->range"
), "../src/analyze/analyze-security.c", 1439, __PRETTY_FUNCTION__
); } while (0)
;
1440
1441 badness_sum += DIV_ROUND_UP(badness * a->weight, a->range)({ const typeof((badness * a->weight)) __unique_prefix_X23
= ((badness * a->weight)); const typeof((a->range)) __unique_prefix_Y24
= ((a->range)); (__unique_prefix_X23 / __unique_prefix_Y24
+ !!(__unique_prefix_X23 % __unique_prefix_Y24)); })
;
1442 weight_sum += a->weight;
1443 }
1444
1445 if (details_table
13.1
'details_table' is null
) {
14
Taking false branch
1446 const char *checkmark, *description, *color = NULL((void*)0);
1447 TableCell *cell;
1448
1449 if (badness == UINT64_MAX(18446744073709551615UL)) {
1450 checkmark = " ";
1451 description = a->description_na;
1452 color = NULL((void*)0);
1453 } else if (badness == a->range) {
1454 checkmark = special_glyph(CROSS_MARK);
1455 description = a->description_bad;
1456 color = ansi_highlight_red();
1457 } else if (badness == 0) {
1458 checkmark = special_glyph(CHECK_MARK);
1459 description = a->description_good;
1460 color = ansi_highlight_green();
1461 } else {
1462 checkmark = special_glyph(CROSS_MARK);
1463 description = NULL((void*)0);
1464 color = ansi_highlight_red();
1465 }
1466
1467 if (d)
1468 description = d;
1469
1470 r = table_add_cell_full(details_table, &cell, TABLE_STRING, checkmark, 1, 1, 0, 0, 0);
1471 if (r < 0)
1472 return log_error_errno(r, "Failed to add cell to table: %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/analyze/analyze-security.c", 1472, __func__, "Failed to add cell to table: %m"
) : -abs(_e); })
;
1473 if (color)
1474 (void) table_set_color(details_table, cell, color);
1475
1476 r = table_add_cell(details_table, &cell, TABLE_STRING, a->id);
1477 if (r < 0)
1478 return log_error_errno(r, "Failed to add cell to table: %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/analyze/analyze-security.c", 1478, __func__, "Failed to add cell to table: %m"
) : -abs(_e); })
;
1479 if (a->url)
1480 (void) table_set_url(details_table, cell, a->url);
1481
1482 r = table_add_cell(details_table, NULL((void*)0), TABLE_STRING, description);
1483 if (r < 0)
1484 return log_error_errno(r, "Failed to add cell to table: %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/analyze/analyze-security.c", 1484, __func__, "Failed to add cell to table: %m"
) : -abs(_e); })
;
1485
1486 r = table_add_cell(details_table, &cell, TABLE_UINT64, &a->weight);
1487 if (r < 0)
1488 return log_error_errno(r, "Failed to add cell to table: %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/analyze/analyze-security.c", 1488, __func__, "Failed to add cell to table: %m"
) : -abs(_e); })
;
1489 (void) table_set_align_percent(details_table, cell, 100);
1490
1491 r = table_add_cell(details_table, &cell, TABLE_UINT64, &badness);
1492 if (r < 0)
1493 return log_error_errno(r, "Failed to add cell to table: %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/analyze/analyze-security.c", 1493, __func__, "Failed to add cell to table: %m"
) : -abs(_e); })
;
1494 (void) table_set_align_percent(details_table, cell, 100);
1495
1496 r = table_add_cell(details_table, &cell, TABLE_UINT64, &a->range);
1497 if (r < 0)
1498 return log_error_errno(r, "Failed to add cell to table: %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/analyze/analyze-security.c", 1498, __func__, "Failed to add cell to table: %m"
) : -abs(_e); })
;
1499 (void) table_set_align_percent(details_table, cell, 100);
1500
1501 r = table_add_cell(details_table, &cell, TABLE_EMPTY, NULL((void*)0));
1502 if (r < 0)
1503 return log_error_errno(r, "Failed to add cell to table: %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/analyze/analyze-security.c", 1503, __func__, "Failed to add cell to table: %m"
) : -abs(_e); })
;
1504 (void) table_set_align_percent(details_table, cell, 100);
1505 }
1506 }
1507
1508 assert(weight_sum > 0)do { if ((__builtin_expect(!!(!(weight_sum > 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("weight_sum > 0"), "../src/analyze/analyze-security.c"
, 1508, __PRETTY_FUNCTION__); } while (0)
;
1509
1510 if (details_table) {
1511 size_t row;
1512
1513 for (row = 1; row < table_get_rows(details_table); row++) {
1514 char buf[DECIMAL_STR_MAX(uint64_t)(2+(sizeof(uint64_t) <= 1 ? 3 : sizeof(uint64_t) <= 2 ?
5 : sizeof(uint64_t) <= 4 ? 10 : sizeof(uint64_t) <= 8
? 20 : sizeof(int[-2*(sizeof(uint64_t) > 8)])))
+ 1 + DECIMAL_STR_MAX(uint64_t)(2+(sizeof(uint64_t) <= 1 ? 3 : sizeof(uint64_t) <= 2 ?
5 : sizeof(uint64_t) <= 4 ? 10 : sizeof(uint64_t) <= 8
? 20 : sizeof(int[-2*(sizeof(uint64_t) > 8)])))
+ 1];
1515 const uint64_t *weight, *badness, *range;
1516 TableCell *cell;
1517 uint64_t x;
1518
1519 assert_se(weight = table_get_at(details_table, row, 3))do { if ((__builtin_expect(!!(!(weight = table_get_at(details_table
, row, 3))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, (
"weight = table_get_at(details_table, row, 3)"), "../src/analyze/analyze-security.c"
, 1519, __PRETTY_FUNCTION__); } while (0)
;
1520 assert_se(badness = table_get_at(details_table, row, 4))do { if ((__builtin_expect(!!(!(badness = table_get_at(details_table
, row, 4))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, (
"badness = table_get_at(details_table, row, 4)"), "../src/analyze/analyze-security.c"
, 1520, __PRETTY_FUNCTION__); } while (0)
;
1521 assert_se(range = table_get_at(details_table, row, 5))do { if ((__builtin_expect(!!(!(range = table_get_at(details_table
, row, 5))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, (
"range = table_get_at(details_table, row, 5)"), "../src/analyze/analyze-security.c"
, 1521, __PRETTY_FUNCTION__); } while (0)
;
1522
1523 if (*badness == UINT64_MAX(18446744073709551615UL) || *badness == 0)
1524 continue;
1525
1526 assert_se(cell = table_get_cell(details_table, row, 6))do { if ((__builtin_expect(!!(!(cell = table_get_cell(details_table
, row, 6))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, (
"cell = table_get_cell(details_table, row, 6)"), "../src/analyze/analyze-security.c"
, 1526, __PRETTY_FUNCTION__); } while (0)
;
1527
1528 x = DIV_ROUND_UP(DIV_ROUND_UP(*badness * *weight * 100U, *range), weight_sum)({ const typeof((({ const typeof((*badness * *weight * 100U))
__unique_prefix_X25 = ((*badness * *weight * 100U)); const typeof
((*range)) __unique_prefix_Y26 = ((*range)); (__unique_prefix_X25
/ __unique_prefix_Y26 + !!(__unique_prefix_X25 % __unique_prefix_Y26
)); }))) __unique_prefix_X27 = ((({ const typeof((*badness * *
weight * 100U)) __unique_prefix_X25 = ((*badness * *weight * 100U
)); const typeof((*range)) __unique_prefix_Y26 = ((*range)); (
__unique_prefix_X25 / __unique_prefix_Y26 + !!(__unique_prefix_X25
% __unique_prefix_Y26)); }))); const typeof((weight_sum)) __unique_prefix_Y28
= ((weight_sum)); (__unique_prefix_X27 / __unique_prefix_Y28
+ !!(__unique_prefix_X27 % __unique_prefix_Y28)); })
;
1529 xsprintf(buf, "%" PRIu64 ".%" PRIu64, x / 10, x % 10)do { if ((__builtin_expect(!!(!(((size_t) snprintf(buf, __extension__
(__builtin_choose_expr( !__builtin_types_compatible_p(typeof
(buf), typeof(&*(buf))), sizeof(buf)/sizeof((buf)[0]), ((
void)0))), "%" "l" "u" ".%" "l" "u", x / 10, x % 10) < (__extension__
(__builtin_choose_expr( !__builtin_types_compatible_p(typeof
(buf), typeof(&*(buf))), sizeof(buf)/sizeof((buf)[0]), ((
void)0))))))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD,
("xsprintf: " "buf" "[] must be big enough"), "../src/analyze/analyze-security.c"
, 1529, __PRETTY_FUNCTION__); } while (0)
;
1530
1531 r = table_update(details_table, cell, TABLE_STRING, buf);
1532 if (r < 0)
1533 return log_error_errno(r, "Failed to update cell in table: %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/analyze/analyze-security.c", 1533, __func__, "Failed to update cell in table: %m"
) : -abs(_e); })
;
1534 }
1535
1536 r = table_print(details_table, stdoutstdout);
1537 if (r < 0)
1538 return log_error_errno(r, "Failed to output table: %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/analyze/analyze-security.c", 1538, __func__, "Failed to output table: %m"
) : -abs(_e); })
;
1539 }
1540
1541 exposure = DIV_ROUND_UP(badness_sum * 100U, weight_sum)({ const typeof((badness_sum * 100U)) __unique_prefix_X29 = (
(badness_sum * 100U)); const typeof((weight_sum)) __unique_prefix_Y30
= ((weight_sum)); (__unique_prefix_X29 / __unique_prefix_Y30
+ !!(__unique_prefix_X29 % __unique_prefix_Y30)); })
;
1542
1543 for (i = 0; i < ELEMENTSOF(badness_table)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(badness_table), typeof(&*(badness_table))), sizeof
(badness_table)/sizeof((badness_table)[0]), ((void)0)))
; i++)
1544 if (exposure >= badness_table[i].exposure)
1545 break;
1546
1547 assert(i < ELEMENTSOF(badness_table))do { if ((__builtin_expect(!!(!(i < __extension__ (__builtin_choose_expr
( !__builtin_types_compatible_p(typeof(badness_table), typeof
(&*(badness_table))), sizeof(badness_table)/sizeof((badness_table
)[0]), ((void)0))))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("i < ELEMENTSOF(badness_table)"), "../src/analyze/analyze-security.c"
, 1547, __PRETTY_FUNCTION__); } while (0)
;
1548
1549 if (details_table) {
1550 _cleanup_free___attribute__((cleanup(freep))) char *clickable = NULL((void*)0);
1551 const char *name;
1552
1553 /* If we shall output the details table, also print the brief summary underneath */
1554
1555 if (info->fragment_path) {
1556 r = terminal_urlify_path(info->fragment_path, info->id, &clickable);
1557 if (r < 0)
1558 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/analyze/analyze-security.c"
, 1558, __func__)
;
1559
1560 name = clickable;
1561 } else
1562 name = info->id;
1563
1564 printf("\n%s %sOverall exposure level for %s%s: %s%" PRIu64"l" "u" ".%" PRIu64"l" "u" " %s%s %s\n",
1565 special_glyph(ARROW),
1566 ansi_highlight(),
1567 name,
1568 ansi_normal(),
1569 colors_enabled() ? strempty(badness_table[i].color) : "",
1570 exposure / 10, exposure % 10,
1571 badness_table[i].name,
1572 ansi_normal(),
1573 special_glyph(badness_table[i].smiley));
1574 }
1575
1576 fflush(stdoutstdout);
1577
1578 if (overview_table) {
1579 char buf[DECIMAL_STR_MAX(uint64_t)(2+(sizeof(uint64_t) <= 1 ? 3 : sizeof(uint64_t) <= 2 ?
5 : sizeof(uint64_t) <= 4 ? 10 : sizeof(uint64_t) <= 8
? 20 : sizeof(int[-2*(sizeof(uint64_t) > 8)])))
+ 1 + DECIMAL_STR_MAX(uint64_t)(2+(sizeof(uint64_t) <= 1 ? 3 : sizeof(uint64_t) <= 2 ?
5 : sizeof(uint64_t) <= 4 ? 10 : sizeof(uint64_t) <= 8
? 20 : sizeof(int[-2*(sizeof(uint64_t) > 8)])))
+ 1];
1580 TableCell *cell;
1581
1582 r = table_add_cell(overview_table, &cell, TABLE_STRING, info->id);
1583 if (r < 0)
1584 return log_error_errno(r, "Failed to add cell to table: %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/analyze/analyze-security.c", 1584, __func__, "Failed to add cell to table: %m"
) : -abs(_e); })
;
1585 if (info->fragment_path) {
1586 _cleanup_free___attribute__((cleanup(freep))) char *url = NULL((void*)0);
1587
1588 r = file_url_from_path(info->fragment_path, &url);
1589 if (r < 0)
1590 return log_error_errno(r, "Failed to generate URL from path: %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/analyze/analyze-security.c", 1590, __func__, "Failed to generate URL from path: %m"
) : -abs(_e); })
;
1591
1592 (void) table_set_url(overview_table, cell, url);
1593 }
1594
1595 xsprintf(buf, "%" PRIu64 ".%" PRIu64, exposure / 10, exposure % 10)do { if ((__builtin_expect(!!(!(((size_t) snprintf(buf, __extension__
(__builtin_choose_expr( !__builtin_types_compatible_p(typeof
(buf), typeof(&*(buf))), sizeof(buf)/sizeof((buf)[0]), ((
void)0))), "%" "l" "u" ".%" "l" "u", exposure / 10, exposure %
10) < (__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(buf), typeof(&*(buf))), sizeof(buf)/sizeof((buf)[
0]), ((void)0))))))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD
, ("xsprintf: " "buf" "[] must be big enough"), "../src/analyze/analyze-security.c"
, 1595, __PRETTY_FUNCTION__); } while (0)
;
1596 r = table_add_cell(overview_table, &cell, TABLE_STRING, buf);
1597 if (r < 0)
1598 return log_error_errno(r, "Failed to add cell to table: %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/analyze/analyze-security.c", 1598, __func__, "Failed to add cell to table: %m"
) : -abs(_e); })
;
1599 (void) table_set_align_percent(overview_table, cell, 100);
1600
1601 r = table_add_cell(overview_table, &cell, TABLE_STRING, badness_table[i].name);
1602 if (r < 0)
1603 return log_error_errno(r, "Failed to add cell to table: %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/analyze/analyze-security.c", 1603, __func__, "Failed to add cell to table: %m"
) : -abs(_e); })
;
1604 (void) table_set_color(overview_table, cell, strempty(badness_table[i].color));
1605
1606 r = table_add_cell(overview_table, NULL((void*)0), TABLE_STRING, special_glyph(badness_table[i].smiley));
1607 if (r < 0)
1608 return log_error_errno(r, "Failed to add cell to table: %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/analyze/analyze-security.c", 1608, __func__, "Failed to add cell to table: %m"
) : -abs(_e); })
;
1609 }
1610
1611 return 0;
1612}
1613
1614static int property_read_restrict_address_families(
1615 sd_bus *bus,
1616 const char *member,
1617 sd_bus_message *m,
1618 sd_bus_error *error,
1619 void *userdata) {
1620
1621 struct security_info *info = userdata;
1622 int whitelist, r;
1623
1624 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/analyze/analyze-security.c"
, 1624, __PRETTY_FUNCTION__); } while (0)
;
1625 assert(member)do { if ((__builtin_expect(!!(!(member)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("member"), "../src/analyze/analyze-security.c"
, 1625, __PRETTY_FUNCTION__); } while (0)
;
1626 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/analyze/analyze-security.c"
, 1626, __PRETTY_FUNCTION__); } while (0)
;
1627
1628 r = sd_bus_message_enter_container(m, 'r', "bas");
1629 if (r < 0)
1630 return r;
1631
1632 r = sd_bus_message_read(m, "b", &whitelist);
1633 if (r < 0)
1634 return r;
1635
1636 info->restrict_address_family_inet =
1637 info->restrict_address_family_unix =
1638 info->restrict_address_family_netlink =
1639 info->restrict_address_family_packet =
1640 info->restrict_address_family_other = whitelist;
1641
1642 r = sd_bus_message_enter_container(m, 'a', "s");
1643 if (r < 0)
1644 return r;
1645
1646 for (;;) {
1647 const char *name;
1648
1649 r = sd_bus_message_read(m, "s", &name);
1650 if (r < 0)
1651 return r;
1652 if (r == 0)
1653 break;
1654
1655 if (STR_IN_SET(name, "AF_INET", "AF_INET6")(!!strv_find((((char**) ((const char*[]) { "AF_INET", "AF_INET6"
, ((void*)0) }))), (name)))
)
1656 info->restrict_address_family_inet = !whitelist;
1657 else if (streq(name, "AF_UNIX")(strcmp((name),("AF_UNIX")) == 0))
1658 info->restrict_address_family_unix = !whitelist;
1659 else if (streq(name, "AF_NETLINK")(strcmp((name),("AF_NETLINK")) == 0))
1660 info->restrict_address_family_netlink = !whitelist;
1661 else if (streq(name, "AF_PACKET")(strcmp((name),("AF_PACKET")) == 0))
1662 info->restrict_address_family_packet = !whitelist;
1663 else
1664 info->restrict_address_family_other = !whitelist;
1665 }
1666
1667 r = sd_bus_message_exit_container(m);
1668 if (r < 0)
1669 return r;
1670
1671 return sd_bus_message_exit_container(m);
1672}
1673
1674static int property_read_system_call_filter(
1675 sd_bus *bus,
1676 const char *member,
1677 sd_bus_message *m,
1678 sd_bus_error *error,
1679 void *userdata) {
1680
1681 struct security_info *info = userdata;
1682 int whitelist, r;
1683
1684 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/analyze/analyze-security.c"
, 1684, __PRETTY_FUNCTION__); } while (0)
;
1685 assert(member)do { if ((__builtin_expect(!!(!(member)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("member"), "../src/analyze/analyze-security.c"
, 1685, __PRETTY_FUNCTION__); } while (0)
;
1686 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/analyze/analyze-security.c"
, 1686, __PRETTY_FUNCTION__); } while (0)
;
1687
1688 r = sd_bus_message_enter_container(m, 'r', "bas");
1689 if (r < 0)
1690 return r;
1691
1692 r = sd_bus_message_read(m, "b", &whitelist);
1693 if (r < 0)
1694 return r;
1695
1696 info->system_call_filter_whitelist = whitelist;
1697
1698 r = sd_bus_message_enter_container(m, 'a', "s");
1699 if (r < 0)
1700 return r;
1701
1702 for (;;) {
1703 const char *name;
1704
1705 r = sd_bus_message_read(m, "s", &name);
1706 if (r < 0)
1707 return r;
1708 if (r == 0)
1709 break;
1710
1711 r = set_ensure_allocated(&info->system_call_filter, &string_hash_ops)internal_set_ensure_allocated(&info->system_call_filter
, &string_hash_ops )
;
1712 if (r < 0)
1713 return r;
1714
1715 r = set_put_strdup(info->system_call_filter, name);
1716 if (r < 0)
1717 return r;
1718 }
1719
1720 r = sd_bus_message_exit_container(m);
1721 if (r < 0)
1722 return r;
1723
1724 return sd_bus_message_exit_container(m);
1725}
1726
1727static int property_read_ip_address_allow(
1728 sd_bus *bus,
1729 const char *member,
1730 sd_bus_message *m,
1731 sd_bus_error *error,
1732 void *userdata) {
1733
1734 struct security_info *info = userdata;
1735 bool_Bool deny_ipv4 = false0, deny_ipv6 = false0;
1736 int r;
1737
1738 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/analyze/analyze-security.c"
, 1738, __PRETTY_FUNCTION__); } while (0)
;
1739 assert(member)do { if ((__builtin_expect(!!(!(member)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("member"), "../src/analyze/analyze-security.c"
, 1739, __PRETTY_FUNCTION__); } while (0)
;
1740 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/analyze/analyze-security.c"
, 1740, __PRETTY_FUNCTION__); } while (0)
;
1741
1742 r = sd_bus_message_enter_container(m, 'a', "(iayu)");
1743 if (r < 0)
1744 return r;
1745
1746 for (;;) {
1747 const void *data;
1748 size_t size;
1749 int32_t family;
1750 uint32_t prefixlen;
1751
1752 r = sd_bus_message_enter_container(m, 'r', "iayu");
1753 if (r < 0)
1754 return r;
1755 if (r == 0)
1756 break;
1757
1758 r = sd_bus_message_read(m, "i", &family);
1759 if (r < 0)
1760 return r;
1761
1762 r = sd_bus_message_read_array(m, 'y', &data, &size);
1763 if (r < 0)
1764 return r;
1765
1766 r = sd_bus_message_read(m, "u", &prefixlen);
1767 if (r < 0)
1768 return r;
1769
1770 r = sd_bus_message_exit_container(m);
1771 if (r < 0)
1772 return r;
1773
1774 if (streq(member, "IPAddressAllow")(strcmp((member),("IPAddressAllow")) == 0)) {
1775 union in_addr_union u;
1776
1777 if (family == AF_INET2 && size == 4 && prefixlen == 8)
1778 memcpy(&u.in, data, size);
1779 else if (family == AF_INET610 && size == 16 && prefixlen == 128)
1780 memcpy(&u.in6, data, size);
1781 else {
1782 info->ip_address_allow_other = true1;
1783 continue;
1784 }
1785
1786 if (in_addr_is_localhost(family, &u))
1787 info->ip_address_allow_localhost = true1;
1788 else
1789 info->ip_address_allow_other = true1;
1790 } else {
1791 assert(streq(member, "IPAddressDeny"))do { if ((__builtin_expect(!!(!((strcmp((member),("IPAddressDeny"
)) == 0))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("streq(member, \"IPAddressDeny\")"
), "../src/analyze/analyze-security.c", 1791, __PRETTY_FUNCTION__
); } while (0)
;
1792
1793 if (family == AF_INET2 && size == 4 && prefixlen == 0)
1794 deny_ipv4 = true1;
1795 else if (family == AF_INET610 && size == 16 && prefixlen == 0)
1796 deny_ipv6 = true1;
1797 }
1798 }
1799
1800 info->ip_address_deny_all = deny_ipv4 && deny_ipv6;
1801
1802 return sd_bus_message_exit_container(m);
1803}
1804
1805static int property_read_device_allow(
1806 sd_bus *bus,
1807 const char *member,
1808 sd_bus_message *m,
1809 sd_bus_error *error,
1810 void *userdata) {
1811
1812 struct security_info *info = userdata;
1813 size_t n = 0;
1814 int r;
1815
1816 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/analyze/analyze-security.c"
, 1816, __PRETTY_FUNCTION__); } while (0)
;
1817 assert(member)do { if ((__builtin_expect(!!(!(member)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("member"), "../src/analyze/analyze-security.c"
, 1817, __PRETTY_FUNCTION__); } while (0)
;
1818 assert(m)do { if ((__builtin_expect(!!(!(m)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("m"), "../src/analyze/analyze-security.c"
, 1818, __PRETTY_FUNCTION__); } while (0)
;
1819
1820 r = sd_bus_message_enter_container(m, 'a', "(ss)");
1821 if (r < 0)
1822 return r;
1823
1824 for (;;) {
1825 const char *name, *policy;
1826
1827 r = sd_bus_message_read(m, "(ss)", &name, &policy);
1828 if (r < 0)
1829 return r;
1830 if (r == 0)
1831 break;
1832
1833 n++;
1834 }
1835
1836 info->device_allow_non_empty = n > 0;
1837
1838 return sd_bus_message_exit_container(m);
1839}
1840
1841static int acquire_security_info(sd_bus *bus, const char *name, struct security_info *info, AnalyzeSecurityFlags flags) {
1842
1843 static const struct bus_properties_map security_map[] = {
1844 { "AmbientCapabilities", "t", NULL((void*)0), offsetof(struct security_info, ambient_capabilities)__builtin_offsetof(struct security_info, ambient_capabilities
)
},
1845 { "CapabilityBoundingSet", "t", NULL((void*)0), offsetof(struct security_info, capability_bounding_set)__builtin_offsetof(struct security_info, capability_bounding_set
)
},
1846 { "DefaultDependencies", "b", NULL((void*)0), offsetof(struct security_info, default_dependencies)__builtin_offsetof(struct security_info, default_dependencies
)
},
1847 { "Delegate", "b", NULL((void*)0), offsetof(struct security_info, delegate)__builtin_offsetof(struct security_info, delegate) },
1848 { "DeviceAllow", "a(ss)", property_read_device_allow, 0 },
1849 { "DevicePolicy", "s", NULL((void*)0), offsetof(struct security_info, device_policy)__builtin_offsetof(struct security_info, device_policy) },
1850 { "DynamicUser", "b", NULL((void*)0), offsetof(struct security_info, dynamic_user)__builtin_offsetof(struct security_info, dynamic_user) },
1851 { "FragmentPath", "s", NULL((void*)0), offsetof(struct security_info, fragment_path)__builtin_offsetof(struct security_info, fragment_path) },
1852 { "IPAddressAllow", "a(iayu)", property_read_ip_address_allow, 0 },
1853 { "IPAddressDeny", "a(iayu)", property_read_ip_address_allow, 0 },
1854 { "Id", "s", NULL((void*)0), offsetof(struct security_info, id)__builtin_offsetof(struct security_info, id) },
1855 { "KeyringMode", "s", NULL((void*)0), offsetof(struct security_info, keyring_mode)__builtin_offsetof(struct security_info, keyring_mode) },
1856 { "LoadState", "s", NULL((void*)0), offsetof(struct security_info, load_state)__builtin_offsetof(struct security_info, load_state) },
1857 { "LockPersonality", "b", NULL((void*)0), offsetof(struct security_info, lock_personality)__builtin_offsetof(struct security_info, lock_personality) },
1858 { "MemoryDenyWriteExecute", "b", NULL((void*)0), offsetof(struct security_info, memory_deny_write_execute)__builtin_offsetof(struct security_info, memory_deny_write_execute
)
},
1859 { "NoNewPrivileges", "b", NULL((void*)0), offsetof(struct security_info, no_new_privileges)__builtin_offsetof(struct security_info, no_new_privileges) },
1860 { "NotifyAccess", "s", NULL((void*)0), offsetof(struct security_info, notify_access)__builtin_offsetof(struct security_info, notify_access) },
1861 { "PrivateDevices", "b", NULL((void*)0), offsetof(struct security_info, private_devices)__builtin_offsetof(struct security_info, private_devices) },
1862 { "PrivateMounts", "b", NULL((void*)0), offsetof(struct security_info, private_mounts)__builtin_offsetof(struct security_info, private_mounts) },
1863 { "PrivateNetwork", "b", NULL((void*)0), offsetof(struct security_info, private_network)__builtin_offsetof(struct security_info, private_network) },
1864 { "PrivateTmp", "b", NULL((void*)0), offsetof(struct security_info, private_tmp)__builtin_offsetof(struct security_info, private_tmp) },
1865 { "PrivateUsers", "b", NULL((void*)0), offsetof(struct security_info, private_users)__builtin_offsetof(struct security_info, private_users) },
1866 { "PrivateUsers", "b", NULL((void*)0), offsetof(struct security_info, private_users)__builtin_offsetof(struct security_info, private_users) },
1867 { "ProtectControlGroups", "b", NULL((void*)0), offsetof(struct security_info, protect_control_groups)__builtin_offsetof(struct security_info, protect_control_groups
)
},
1868 { "ProtectHome", "s", NULL((void*)0), offsetof(struct security_info, protect_home)__builtin_offsetof(struct security_info, protect_home) },
1869 { "ProtectKernelModules", "b", NULL((void*)0), offsetof(struct security_info, protect_kernel_modules)__builtin_offsetof(struct security_info, protect_kernel_modules
)
},
1870 { "ProtectKernelTunables", "b", NULL((void*)0), offsetof(struct security_info, protect_kernel_tunables)__builtin_offsetof(struct security_info, protect_kernel_tunables
)
},
1871 { "ProtectSystem", "s", NULL((void*)0), offsetof(struct security_info, protect_system)__builtin_offsetof(struct security_info, protect_system) },
1872 { "RemoveIPC", "b", NULL((void*)0), offsetof(struct security_info, remove_ipc)__builtin_offsetof(struct security_info, remove_ipc) },
1873 { "RestrictAddressFamilies", "(bas)", property_read_restrict_address_families, 0 },
1874 { "RestrictNamespaces", "t", NULL((void*)0), offsetof(struct security_info, restrict_namespaces)__builtin_offsetof(struct security_info, restrict_namespaces) },
1875 { "RestrictRealtime", "b", NULL((void*)0), offsetof(struct security_info, restrict_realtime)__builtin_offsetof(struct security_info, restrict_realtime) },
1876 { "RestrictSUIDSGID", "b", NULL((void*)0), offsetof(struct security_info, restrict_suid_sgid)__builtin_offsetof(struct security_info, restrict_suid_sgid) },
1877 { "RootDirectory", "s", NULL((void*)0), offsetof(struct security_info, root_directory)__builtin_offsetof(struct security_info, root_directory) },
1878 { "RootImage", "s", NULL((void*)0), offsetof(struct security_info, root_image)__builtin_offsetof(struct security_info, root_image) },
1879 { "SupplementaryGroups", "as", NULL((void*)0), offsetof(struct security_info, supplementary_groups)__builtin_offsetof(struct security_info, supplementary_groups
)
},
1880 { "SystemCallArchitectures", "as", NULL((void*)0), offsetof(struct security_info, system_call_architectures)__builtin_offsetof(struct security_info, system_call_architectures
)
},
1881 { "SystemCallFilter", "(as)", property_read_system_call_filter, 0 },
1882 { "Type", "s", NULL((void*)0), offsetof(struct security_info, type)__builtin_offsetof(struct security_info, type) },
1883 { "UMask", "u", NULL((void*)0), offsetof(struct security_info, _umask)__builtin_offsetof(struct security_info, _umask) },
1884 { "User", "s", NULL((void*)0), offsetof(struct security_info, user)__builtin_offsetof(struct security_info, user) },
1885 {}
1886 };
1887
1888 _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0});
1889 _cleanup_free___attribute__((cleanup(freep))) char *path = NULL((void*)0);
1890 int r;
1891
1892 /* Note: this mangles *info on failure! */
1893
1894 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/analyze/analyze-security.c"
, 1894, __PRETTY_FUNCTION__); } while (0)
;
1895 assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("name"), "../src/analyze/analyze-security.c"
, 1895, __PRETTY_FUNCTION__); } while (0)
;
1896 assert(info)do { if ((__builtin_expect(!!(!(info)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("info"), "../src/analyze/analyze-security.c"
, 1896, __PRETTY_FUNCTION__); } while (0)
;
1897
1898 path = unit_dbus_path_from_name(name);
1899 if (!path)
1900 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/analyze/analyze-security.c"
, 1900, __func__)
;
1901
1902 r = bus_map_all_properties(bus,
1903 "org.freedesktop.systemd1",
1904 path,
1905 security_map,
1906 BUS_MAP_STRDUP|BUS_MAP_BOOLEAN_AS_BOOL,
1907 &error,
1908 NULL((void*)0),
1909 info);
1910 if (r < 0)
1911 return log_error_errno(r, "Failed to get unit properties: %s", bus_error_message(&error, r))({ 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/analyze/analyze-security.c", 1911, __func__, "Failed to get unit properties: %s"
, bus_error_message(&error, r)) : -abs(_e); })
;
1912
1913 if (!streq_ptr(info->load_state, "loaded")) {
1914
1915 if (FLAGS_SET(flags, ANALYZE_SECURITY_ONLY_LOADED)(((flags) & (ANALYZE_SECURITY_ONLY_LOADED)) == (ANALYZE_SECURITY_ONLY_LOADED
))
)
1916 return -EMEDIUMTYPE124;
1917
1918 if (streq_ptr(info->load_state, "not-found"))
1919 log_error("Unit %s not found, cannot analyze.", name)({ 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/analyze/analyze-security.c", 1919, __func__, "Unit %s not found, cannot analyze."
, name) : -abs(_e); })
;
1920 else if (streq_ptr(info->load_state, "masked"))
1921 log_error("Unit %s is masked, cannot analyze.", name)({ 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/analyze/analyze-security.c", 1921, __func__, "Unit %s is masked, cannot analyze."
, name) : -abs(_e); })
;
1922 else
1923 log_error("Unit %s not loaded properly, cannot analyze.", name)({ 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/analyze/analyze-security.c", 1923, __func__, "Unit %s not loaded properly, cannot analyze."
, name) : -abs(_e); })
;
1924
1925 return -EINVAL22;
1926 }
1927
1928 if (FLAGS_SET(flags, ANALYZE_SECURITY_ONLY_LONG_RUNNING)(((flags) & (ANALYZE_SECURITY_ONLY_LONG_RUNNING)) == (ANALYZE_SECURITY_ONLY_LONG_RUNNING
))
&& streq_ptr(info->type, "oneshot"))
1929 return -EMEDIUMTYPE124;
1930
1931 if (info->private_devices ||
1932 info->private_tmp ||
1933 info->protect_control_groups ||
1934 info->protect_kernel_tunables ||
1935 info->protect_kernel_modules ||
1936 !streq_ptr(info->protect_home, "no") ||
1937 !streq_ptr(info->protect_system, "no") ||
1938 info->root_image)
1939 info->private_mounts = true1;
1940
1941 if (info->protect_kernel_modules)
1942 info->capability_bounding_set &= ~(UINT64_C(1)1UL << CAP_SYS_MODULE16);
1943
1944 if (info->private_devices)
1945 info->capability_bounding_set &= ~((UINT64_C(1)1UL << CAP_MKNOD27) |
1946 (UINT64_C(1)1UL << CAP_SYS_RAWIO17));
1947
1948 return 0;
1949}
1950
1951static int analyze_security_one(sd_bus *bus, const char *name, Table* overview_table, AnalyzeSecurityFlags flags) {
1952 _cleanup_(security_info_free)__attribute__((cleanup(security_info_free))) struct security_info info = {
1953 .default_dependencies = true1,
1954 .capability_bounding_set = UINT64_MAX(18446744073709551615UL),
1955 .restrict_namespaces = UINT64_MAX(18446744073709551615UL),
1956 ._umask = 0002,
1957 };
1958 int r;
1959
1960 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/analyze/analyze-security.c"
, 1960, __PRETTY_FUNCTION__); } while (0)
;
1961 assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("name"), "../src/analyze/analyze-security.c"
, 1961, __PRETTY_FUNCTION__); } while (0)
;
1962
1963 r = acquire_security_info(bus, name, &info, flags);
1964 if (r == -EMEDIUMTYPE124) /* Ignore this one because not loaded or Type is oneshot */
1965 return 0;
1966 if (r < 0)
1967 return r;
1968
1969 r = assess(&info, overview_table, flags);
1970 if (r < 0)
1971 return r;
1972
1973 return 0;
1974}
1975
1976int analyze_security(sd_bus *bus, char **units, AnalyzeSecurityFlags flags) {
1977 _cleanup_(table_unrefp)__attribute__((cleanup(table_unrefp))) Table *overview_table = NULL((void*)0);
1978 int ret = 0, r;
1979
1980 assert(bus)do { if ((__builtin_expect(!!(!(bus)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("bus"), "../src/analyze/analyze-security.c"
, 1980, __PRETTY_FUNCTION__); } while (0)
;
1981
1982 if (strv_length(units) != 1) {
1983 overview_table = table_new("UNIT", "EXPOSURE", "PREDICATE", "HAPPY")table_new_internal("UNIT", "EXPOSURE", "PREDICATE", "HAPPY", (
(void*)0))
;
1984 if (!overview_table)
1985 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/analyze/analyze-security.c"
, 1985, __func__)
;
1986 }
1987
1988 if (strv_isempty(units)) {
1989 _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0});
1990 _cleanup_(sd_bus_message_unrefp)__attribute__((cleanup(sd_bus_message_unrefp))) sd_bus_message *reply = NULL((void*)0);
1991 _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **list = NULL((void*)0);
1992 size_t allocated = 0, n = 0;
1993 char **i;
1994
1995 r = sd_bus_call_method(
1996 bus,
1997 "org.freedesktop.systemd1",
1998 "/org/freedesktop/systemd1",
1999 "org.freedesktop.systemd1.Manager",
2000 "ListUnits",
2001 &error, &reply,
2002 NULL((void*)0));
2003 if (r < 0)
2004 return log_error_errno(r, "Failed to list units: %s", bus_error_message(&error, r))({ 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/analyze/analyze-security.c", 2004, __func__, "Failed to list units: %s"
, bus_error_message(&error, r)) : -abs(_e); })
;
2005
2006 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
2007 if (r < 0)
2008 return bus_log_parse_error(r);
2009
2010 for (;;) {
2011 UnitInfo info;
2012 char *copy = NULL((void*)0);
2013
2014 r = bus_parse_unit_info(reply, &info);
2015 if (r < 0)
2016 return bus_log_parse_error(r);
2017 if (r == 0)
2018 break;
2019
2020 if (!endswith(info.id, ".service"))
2021 continue;
2022
2023 if (!GREEDY_REALLOC(list, allocated, n+2)greedy_realloc((void**) &(list), &(allocated), (n+2),
sizeof((list)[0]))
)
2024 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/analyze/analyze-security.c"
, 2024, __func__)
;
2025
2026 copy = strdup(info.id);
2027 if (!copy)
2028 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/analyze/analyze-security.c"
, 2028, __func__)
;
2029
2030 list[n++] = copy;
2031 list[n] = NULL((void*)0);
2032 }
2033
2034 strv_sort(list);
2035
2036 flags |= ANALYZE_SECURITY_SHORT|ANALYZE_SECURITY_ONLY_LOADED|ANALYZE_SECURITY_ONLY_LONG_RUNNING;
2037
2038 STRV_FOREACH(i, list)for ((i) = (list); (i) && *(i); (i)++) {
2039 r = analyze_security_one(bus, *i, overview_table, flags);
2040 if (r < 0 && ret >= 0)
2041 ret = r;
2042 }
2043
2044 } else {
2045 char **i;
2046
2047 STRV_FOREACH(i, units)for ((i) = (units); (i) && *(i); (i)++) {
2048 _cleanup_free___attribute__((cleanup(freep))) char *mangled = NULL((void*)0), *instance = NULL((void*)0);
2049 const char *name;
2050
2051 if (!FLAGS_SET(flags, ANALYZE_SECURITY_SHORT)(((flags) & (ANALYZE_SECURITY_SHORT)) == (ANALYZE_SECURITY_SHORT
))
&& i != units) {
2052 putc('\n', stdoutstdout);
2053 fflush(stdoutstdout);
2054 }
2055
2056 r = unit_name_mangle_with_suffix(*i, 0, ".service", &mangled);
2057 if (r < 0)
2058 return log_error_errno(r, "Failed to mangle unit name '%s': %m", *i)({ 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/analyze/analyze-security.c", 2058, __func__, "Failed to mangle unit name '%s': %m"
, *i) : -abs(_e); })
;
2059
2060 if (!endswith(mangled, ".service")) {
2061 log_error("Unit %s is not a service unit, refusing.", *i)({ 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/analyze/analyze-security.c", 2061, __func__, "Unit %s is not a service unit, refusing."
, *i) : -abs(_e); })
;
2062 return -EINVAL22;
2063 }
2064
2065 if (unit_name_is_valid(mangled, UNIT_NAME_TEMPLATE)) {
2066 r = unit_name_replace_instance(mangled, "test-instance", &instance);
2067 if (r < 0)
2068 return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/analyze/analyze-security.c"
, 2068, __func__)
;
2069
2070 name = instance;
2071 } else
2072 name = mangled;
2073
2074 r = analyze_security_one(bus, name, overview_table, flags);
2075 if (r < 0 && ret >= 0)
2076 ret = r;
2077 }
2078 }
2079
2080 if (overview_table) {
2081 if (!FLAGS_SET(flags, ANALYZE_SECURITY_SHORT)(((flags) & (ANALYZE_SECURITY_SHORT)) == (ANALYZE_SECURITY_SHORT
))
) {
2082 putc('\n', stdoutstdout);
2083 fflush(stdoutstdout);
2084 }
2085
2086 r = table_print(overview_table, stdoutstdout);
2087 if (r < 0)
2088 return log_error_errno(r, "Failed to output table: %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/analyze/analyze-security.c", 2088, __func__, "Failed to output table: %m"
) : -abs(_e); })
;
2089 }
2090
2091 return ret;
2092}