Bug Summary

File:build-scan/../src/basic/selinux-util.c
Warning:line 325, column 11
Potential leak of memory pointed to by 'mycon'

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 selinux-util.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fdenormal-fp-math=preserve-sign,preserve-sign -ffp-contract=fast -fno-rounding-math -ffast-math -ffinite-math-only -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/12.0.0 -include config.h -I src/basic/libbasic.a.p -I src/basic -I ../src/basic -I src/shared -I ../src/shared -I src/systemd -I ../src/systemd -I src/journal -I ../src/journal -I src/journal-remote -I ../src/journal-remote -I src/nspawn -I ../src/nspawn -I src/resolve -I ../src/resolve -I src/timesync -I ../src/timesync -I ../src/time-wait-sync -I src/login -I ../src/login -I src/udev -I ../src/udev -I src/libudev -I ../src/libudev -I src/core -I ../src/core -I ../src/libsystemd/sd-bus -I ../src/libsystemd/sd-device -I ../src/libsystemd/sd-hwdb -I ../src/libsystemd/sd-id128 -I ../src/libsystemd/sd-netlink -I ../src/libsystemd/sd-network -I src/libsystemd-network -I ../src/libsystemd-network -I . -I .. -I /usr/include/blkid -I /usr/include/libmount -D _FILE_OFFSET_BITS=64 -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wwrite-strings -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unused-result -Wno-format-signedness -Wno-error=nonnull -std=gnu99 -fconst-strings -fdebug-compilation-dir /home/mrc0mmand/repos/@redhat-plumbers/systemd-rhel8/build-scan -ferror-limit 19 -fvisibility default -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-07-16-221226-1465241-1 -x c ../src/basic/selinux-util.c
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <errno(*__errno_location ()).h>
4#include <malloc.h>
5#include <stddef.h>
6#include <string.h>
7#include <sys/stat.h>
8#include <sys/time.h>
9#include <sys/un.h>
10#include <syslog.h>
11
12#if HAVE_SELINUX1
13#include <selinux/avc.h>
14#include <selinux/context.h>
15#include <selinux/label.h>
16#include <selinux/selinux.h>
17#endif
18
19#include "alloc-util.h"
20#include "fd-util.h"
21#include "log.h"
22#include "macro.h"
23#include "path-util.h"
24#include "selinux-util.h"
25#include "stdio-util.h"
26#include "time-util.h"
27#include "util.h"
28
29#if HAVE_SELINUX1
30DEFINE_TRIVIAL_CLEANUP_FUNC(char*, freecon)static inline void freeconp(char* *p) { if (*p) freecon(*p); };
31DEFINE_TRIVIAL_CLEANUP_FUNC(context_t, context_free)static inline void context_freep(context_t *p) { if (*p) context_free
(*p); }
;
32
33#define _cleanup_freecon___attribute__((cleanup(freeconp))) _cleanup_(freeconp)__attribute__((cleanup(freeconp)))
34#define _cleanup_context_free___attribute__((cleanup(context_freep))) _cleanup_(context_freep)__attribute__((cleanup(context_freep)))
35
36static int mac_selinux_reload(int seqno);
37
38static int cached_use = -1;
39static struct selabel_handle *label_hnd = NULL((void*)0);
40
41#define log_enforcing(...)({ int _level = (((security_getenforce() == 1 ? 3 : 7))), _e =
((0)), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm
(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((
_realm) << 10 | (_level)), _e, "../src/basic/selinux-util.c"
, 41, __func__, ...) : -abs(_e); })
log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, __VA_ARGS__)({ int _level = (((security_getenforce() == 1 ? 3 : 7))), _e =
((0)), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm
(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((
_realm) << 10 | (_level)), _e, "../src/basic/selinux-util.c"
, 41, __func__, __VA_ARGS__) : -abs(_e); })
42#define log_enforcing_errno(r, ...)({ int _level = ((security_getenforce() == 1 ? 3 : 7)), _e = (
(r)), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(
_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm
) << 10 | (_level)), _e, "../src/basic/selinux-util.c",
42, __func__, ...) : -abs(_e); })
log_full_errno(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, r, __VA_ARGS__)({ int _level = ((security_getenforce() == 1 ? 3 : 7)), _e = (
(r)), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(
_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm
) << 10 | (_level)), _e, "../src/basic/selinux-util.c",
42, __func__, __VA_ARGS__) : -abs(_e); })
43#endif
44
45bool_Bool mac_selinux_use(void) {
46#if HAVE_SELINUX1
47 if (cached_use < 0)
48 cached_use = is_selinux_enabled() > 0;
49
50 return cached_use;
51#else
52 return false0;
53#endif
54}
55
56void mac_selinux_retest(void) {
57#if HAVE_SELINUX1
58 cached_use = -1;
59#endif
60}
61
62int mac_selinux_init(void) {
63 int r = 0;
64
65#if HAVE_SELINUX1
66 usec_t before_timestamp, after_timestamp;
67 struct mallinfo before_mallinfo, after_mallinfo;
68
69 selinux_set_callback(SELINUX_CB_POLICYLOAD4, (union selinux_callback) mac_selinux_reload);
70
71 if (label_hnd)
72 return 0;
73
74 if (!mac_selinux_use())
75 return 0;
76
77 before_mallinfo = mallinfo();
78 before_timestamp = now(CLOCK_MONOTONIC1);
79
80 label_hnd = selabel_open(SELABEL_CTX_FILE0, NULL((void*)0), 0);
81 if (!label_hnd) {
82 log_enforcing_errno(errno, "Failed to initialize SELinux context: %m")({ int _level = ((security_getenforce() == 1 ? 3 : 7)), _e = (
((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm
(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((
_realm) << 10 | (_level)), _e, "../src/basic/selinux-util.c"
, 82, __func__, "Failed to initialize SELinux context: %m") :
-abs(_e); })
;
83 r = security_getenforce() == 1 ? -errno(*__errno_location ()) : 0;
84 } else {
85 char timespan[FORMAT_TIMESPAN_MAX64];
86 int l;
87
88 after_timestamp = now(CLOCK_MONOTONIC1);
89 after_mallinfo = mallinfo();
90
91 l = after_mallinfo.uordblks > before_mallinfo.uordblks ? after_mallinfo.uordblks - before_mallinfo.uordblks : 0;
92
93 log_debug("Successfully loaded SELinux database in %s, size on heap is %iK.",({ 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/basic/selinux-util.c", 95, __func__, "Successfully loaded SELinux database in %s, size on heap is %iK."
, format_timespan(timespan, sizeof(timespan), after_timestamp
- before_timestamp, 0), (l+1023)/1024) : -abs(_e); })
94 format_timespan(timespan, sizeof(timespan), after_timestamp - before_timestamp, 0),({ 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/basic/selinux-util.c", 95, __func__, "Successfully loaded SELinux database in %s, size on heap is %iK."
, format_timespan(timespan, sizeof(timespan), after_timestamp
- before_timestamp, 0), (l+1023)/1024) : -abs(_e); })
95 (l+1023)/1024)({ 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/basic/selinux-util.c", 95, __func__, "Successfully loaded SELinux database in %s, size on heap is %iK."
, format_timespan(timespan, sizeof(timespan), after_timestamp
- before_timestamp, 0), (l+1023)/1024) : -abs(_e); })
;
96 }
97#endif
98
99 return r;
100}
101
102void mac_selinux_finish(void) {
103
104#if HAVE_SELINUX1
105 if (!label_hnd)
106 return;
107
108 selabel_close(label_hnd);
109 label_hnd = NULL((void*)0);
110#endif
111}
112
113#if HAVE_SELINUX1
114static int mac_selinux_reload(int seqno) {
115 struct selabel_handle *backup_label_hnd;
116
117 if (!label_hnd)
118 return 0;
119
120 backup_label_hnd = TAKE_PTR(label_hnd)({ typeof(label_hnd) _ptr_ = (label_hnd); (label_hnd) = ((void
*)0); _ptr_; })
;
121
122 /* try to initialize new handle
123 * on success close backup
124 * on failure restore backup */
125 if (mac_selinux_init() == 0)
126 selabel_close(backup_label_hnd);
127 else
128 label_hnd = backup_label_hnd;
129
130 return 0;
131}
132#endif
133
134int mac_selinux_fix(const char *path, LabelFixFlags flags) {
135
136#if HAVE_SELINUX1
137 char procfs_path[STRLEN("/proc/self/fd/")(sizeof("""/proc/self/fd/""") - 1) + DECIMAL_STR_MAX(int)(2+(sizeof(int) <= 1 ? 3 : sizeof(int) <= 2 ? 5 : sizeof
(int) <= 4 ? 10 : sizeof(int) <= 8 ? 20 : sizeof(int[-2
*(sizeof(int) > 8)])))
];
138 _cleanup_freecon___attribute__((cleanup(freeconp))) char* fcon = NULL((void*)0);
139 _cleanup_close___attribute__((cleanup(closep))) int fd = -1;
140 struct stat st;
141 int r;
142
143 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/basic/selinux-util.c", 143
, __PRETTY_FUNCTION__); } while (0)
;
144
145 /* if mac_selinux_init() wasn't called before we are a NOOP */
146 if (!label_hnd)
147 return 0;
148
149 /* Open the file as O_PATH, to pin it while we determine and adjust the label */
150 fd = open(path, O_NOFOLLOW0400000|O_CLOEXEC02000000|O_PATH010000000);
151 if (fd < 0) {
152 if ((flags & LABEL_IGNORE_ENOENT) && errno(*__errno_location ()) == ENOENT2)
153 return 0;
154
155 return -errno(*__errno_location ());
156 }
157
158 if (fstat(fd, &st) < 0)
159 return -errno(*__errno_location ());
160
161 /* Check for policy reload so 'label_hnd' is kept up-to-date by callbacks */
162 (void) avc_netlink_check_nb();
163
164 if (selabel_lookup_raw(label_hnd, &fcon, path, st.st_mode) < 0) {
165 r = -errno(*__errno_location ());
166
167 /* If there's no label to set, then exit without warning */
168 if (r == -ENOENT2)
169 return 0;
170
171 goto fail;
172 }
173
174 xsprintf(procfs_path, "/proc/self/fd/%i", fd)do { if ((__builtin_expect(!!(!(((size_t) snprintf(procfs_path
, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(procfs_path), typeof(&*(procfs_path))), sizeof(procfs_path
)/sizeof((procfs_path)[0]), ((void)0))), "/proc/self/fd/%i", fd
) < (__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p
(typeof(procfs_path), typeof(&*(procfs_path))), sizeof(procfs_path
)/sizeof((procfs_path)[0]), ((void)0))))))),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("xsprintf: " "procfs_path" "[] must be big enough"
), "../src/basic/selinux-util.c", 174, __PRETTY_FUNCTION__); }
while (0)
;
175 if (setfilecon_raw(procfs_path, fcon) < 0) {
176 _cleanup_freecon___attribute__((cleanup(freeconp))) char *oldcon = NULL((void*)0);
177
178 r = -errno(*__errno_location ());
179
180 /* If the FS doesn't support labels, then exit without warning */
181 if (r == -EOPNOTSUPP95)
182 return 0;
183
184 /* It the FS is read-only and we were told to ignore failures caused by that, suppress error */
185 if (r == -EROFS30 && (flags & LABEL_IGNORE_EROFS))
186 return 0;
187
188 /* If the old label is identical to the new one, suppress any kind of error */
189 if (getfilecon_raw(procfs_path, &oldcon) >= 0 && streq(fcon, oldcon)(strcmp((fcon),(oldcon)) == 0))
190 return 0;
191
192 goto fail;
193 }
194
195 return 0;
196
197fail:
198 log_enforcing_errno(r, "Unable to fix SELinux security context of %s: %m", path)({ int _level = ((security_getenforce() == 1 ? 3 : 7)), _e = (
(r)), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(
_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm
) << 10 | (_level)), _e, "../src/basic/selinux-util.c",
198, __func__, "Unable to fix SELinux security context of %s: %m"
, path) : -abs(_e); })
;
199 if (security_getenforce() == 1)
200 return r;
201#endif
202
203 return 0;
204}
205
206int mac_selinux_apply(const char *path, const char *label) {
207
208#if HAVE_SELINUX1
209 if (!mac_selinux_use())
210 return 0;
211
212 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/basic/selinux-util.c", 212
, __PRETTY_FUNCTION__); } while (0)
;
213 assert(label)do { if ((__builtin_expect(!!(!(label)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("label"), "../src/basic/selinux-util.c",
213, __PRETTY_FUNCTION__); } while (0)
;
214
215 if (setfilecon(path, label) < 0) {
216 log_enforcing_errno(errno, "Failed to set SELinux security context %s on path %s: %m", label, path)({ int _level = ((security_getenforce() == 1 ? 3 : 7)), _e = (
((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm
(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((
_realm) << 10 | (_level)), _e, "../src/basic/selinux-util.c"
, 216, __func__, "Failed to set SELinux security context %s on path %s: %m"
, label, path) : -abs(_e); })
;
217 if (security_getenforce() > 0)
218 return -errno(*__errno_location ());
219 }
220#endif
221 return 0;
222}
223
224int mac_selinux_get_create_label_from_exe(const char *exe, char **label) {
225 int r = -EOPNOTSUPP95;
226
227#if HAVE_SELINUX1
228 _cleanup_freecon___attribute__((cleanup(freeconp))) char *mycon = NULL((void*)0), *fcon = NULL((void*)0);
229 security_class_t sclass;
230
231 assert(exe)do { if ((__builtin_expect(!!(!(exe)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("exe"), "../src/basic/selinux-util.c", 231
, __PRETTY_FUNCTION__); } while (0)
;
232 assert(label)do { if ((__builtin_expect(!!(!(label)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("label"), "../src/basic/selinux-util.c",
232, __PRETTY_FUNCTION__); } while (0)
;
233
234 if (!mac_selinux_use())
235 return -EOPNOTSUPP95;
236
237 r = getcon_raw(&mycon);
238 if (r < 0)
239 return -errno(*__errno_location ());
240
241 r = getfilecon_raw(exe, &fcon);
242 if (r < 0)
243 return -errno(*__errno_location ());
244
245 sclass = string_to_security_class("process");
246 r = security_compute_create_raw(mycon, fcon, sclass, label);
247 if (r < 0)
248 return -errno(*__errno_location ());
249#endif
250
251 return r;
252}
253
254int mac_selinux_get_our_label(char **label) {
255 int r = -EOPNOTSUPP95;
256
257 assert(label)do { if ((__builtin_expect(!!(!(label)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("label"), "../src/basic/selinux-util.c",
257, __PRETTY_FUNCTION__); } while (0)
;
258
259#if HAVE_SELINUX1
260 if (!mac_selinux_use())
261 return -EOPNOTSUPP95;
262
263 r = getcon_raw(label);
264 if (r < 0)
265 return -errno(*__errno_location ());
266#endif
267
268 return r;
269}
270
271int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *exec_label, char **label) {
272 int r = -EOPNOTSUPP95;
273
274#if HAVE_SELINUX1
275 _cleanup_freecon___attribute__((cleanup(freeconp))) char *mycon = NULL((void*)0), *peercon = NULL((void*)0), *fcon = NULL((void*)0);
276 _cleanup_context_free___attribute__((cleanup(context_freep))) context_t pcon = NULL((void*)0), bcon = NULL((void*)0);
277 security_class_t sclass;
278 const char *range = NULL((void*)0);
279
280 assert(socket_fd >= 0)do { if ((__builtin_expect(!!(!(socket_fd >= 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("socket_fd >= 0"), "../src/basic/selinux-util.c"
, 280, __PRETTY_FUNCTION__); } while (0)
;
1
Assuming 'socket_fd' is >= 0
2
Taking false branch
3
Loop condition is false. Exiting loop
281 assert(exe)do { if ((__builtin_expect(!!(!(exe)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("exe"), "../src/basic/selinux-util.c", 281
, __PRETTY_FUNCTION__); } while (0)
;
4
Assuming 'exe' is non-null
5
Taking false branch
6
Loop condition is false. Exiting loop
282 assert(label)do { if ((__builtin_expect(!!(!(label)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("label"), "../src/basic/selinux-util.c",
282, __PRETTY_FUNCTION__); } while (0)
;
7
Assuming 'label' is non-null
8
Taking false branch
9
Loop condition is false. Exiting loop
283
284 if (!mac_selinux_use())
10
Assuming the condition is false
11
Taking false branch
285 return -EOPNOTSUPP95;
286
287 r = getcon_raw(&mycon);
288 if (r < 0)
12
Assuming 'r' is >= 0
13
Taking false branch
289 return -errno(*__errno_location ());
290
291 r = getpeercon_raw(socket_fd, &peercon);
292 if (r < 0)
14
Assuming 'r' is >= 0
15
Taking false branch
293 return -errno(*__errno_location ());
294
295 if (!exec_label) {
16
Assuming 'exec_label' is non-null
17
Taking false branch
296 /* If there is no context set for next exec let's use context
297 of target executable */
298 r = getfilecon_raw(exe, &fcon);
299 if (r < 0)
300 return -errno(*__errno_location ());
301 }
302
303 bcon = context_new(mycon);
304 if (!bcon)
18
Assuming 'bcon' is non-null
19
Taking false branch
305 return -ENOMEM12;
306
307 pcon = context_new(peercon);
308 if (!pcon)
20
Assuming 'pcon' is non-null
21
Taking false branch
309 return -ENOMEM12;
310
311 range = context_range_get(pcon);
312 if (!range)
22
Assuming 'range' is non-null
23
Taking false branch
313 return -errno(*__errno_location ());
314
315 r = context_range_set(bcon, range);
316 if (r)
24
Assuming 'r' is 0
25
Taking false branch
317 return -errno(*__errno_location ());
318
319 freecon(mycon);
320 mycon = strdup(context_str(bcon));
26
Memory is allocated
321 if (!mycon)
27
Assuming 'mycon' is non-null
28
Taking false branch
322 return -ENOMEM12;
323
324 sclass = string_to_security_class("process");
325 r = security_compute_create_raw(mycon, fcon, sclass, label);
29
Potential leak of memory pointed to by 'mycon'
326 if (r < 0)
327 return -errno(*__errno_location ());
328#endif
329
330 return r;
331}
332
333char* mac_selinux_free(char *label) {
334
335#if HAVE_SELINUX1
336 if (!label)
337 return NULL((void*)0);
338
339 if (!mac_selinux_use())
340 return NULL((void*)0);
341
342 freecon(label);
343#endif
344
345 return NULL((void*)0);
346}
347
348#if HAVE_SELINUX1
349static int selinux_create_file_prepare_abspath(const char *abspath, mode_t mode) {
350 _cleanup_freecon___attribute__((cleanup(freeconp))) char *filecon = NULL((void*)0);
351 _cleanup_free___attribute__((cleanup(freep))) char *path = NULL((void*)0);
352 int r;
353
354 assert(abspath)do { if ((__builtin_expect(!!(!(abspath)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("abspath"), "../src/basic/selinux-util.c"
, 354, __PRETTY_FUNCTION__); } while (0)
;
355 assert(path_is_absolute(abspath))do { if ((__builtin_expect(!!(!(path_is_absolute(abspath))),0
))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("path_is_absolute(abspath)"
), "../src/basic/selinux-util.c", 355, __PRETTY_FUNCTION__); }
while (0)
;
356
357 /* Check for policy reload so 'label_hnd' is kept up-to-date by callbacks */
358 (void) avc_netlink_check_nb();
359
360 r = selabel_lookup_raw(label_hnd, &filecon, abspath, mode);
361 if (r < 0) {
362 /* No context specified by the policy? Proceed without setting it. */
363 if (errno(*__errno_location ()) == ENOENT2)
364 return 0;
365
366 log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", abspath)({ int _level = ((security_getenforce() == 1 ? 3 : 7)), _e = (
((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm
(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((
_realm) << 10 | (_level)), _e, "../src/basic/selinux-util.c"
, 366, __func__, "Failed to determine SELinux security context for %s: %m"
, abspath) : -abs(_e); })
;
367 } else {
368 if (setfscreatecon_raw(filecon) >= 0)
369 return 0; /* Success! */
370
371 log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", filecon, abspath)({ int _level = ((security_getenforce() == 1 ? 3 : 7)), _e = (
((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm
(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((
_realm) << 10 | (_level)), _e, "../src/basic/selinux-util.c"
, 371, __func__, "Failed to set SELinux security context %s for %s: %m"
, filecon, abspath) : -abs(_e); })
;
372 }
373
374 if (security_getenforce() > 0)
375 return -errno(*__errno_location ());
376
377 return 0;
378}
379#endif
380
381int mac_selinux_create_file_prepare_at(int dirfd, const char *path, mode_t mode) {
382 int r = 0;
383
384#if HAVE_SELINUX1
385 _cleanup_free___attribute__((cleanup(freep))) char *abspath = NULL((void*)0);
386 _cleanup_close___attribute__((cleanup(closep))) int fd = -1;
387
388 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/basic/selinux-util.c", 388
, __PRETTY_FUNCTION__); } while (0)
;
389
390 if (!label_hnd)
391 return 0;
392
393 if (!path_is_absolute(path)) {
394 _cleanup_free___attribute__((cleanup(freep))) char *p = NULL((void*)0);
395
396 if (dirfd == AT_FDCWD-100)
397 r = safe_getcwd(&p);
398 else
399 r = fd_get_path(dirfd, &p);
400 if (r < 0)
401 return r;
402
403 abspath = path_join(NULL((void*)0), p, path);
404 if (!abspath)
405 return -ENOMEM12;
406
407 path = abspath;
408 }
409
410 r = selinux_create_file_prepare_abspath(path, mode);
411#endif
412 return r;
413}
414
415int mac_selinux_create_file_prepare(const char *path, mode_t mode) {
416 int r = 0;
417
418#if HAVE_SELINUX1
419 _cleanup_free___attribute__((cleanup(freep))) char *abspath = NULL((void*)0);
420
421 assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("path"), "../src/basic/selinux-util.c", 421
, __PRETTY_FUNCTION__); } while (0)
;
422
423 if (!label_hnd)
424 return 0;
425
426 r = path_make_absolute_cwd(path, &abspath);
427 if (r < 0)
428 return r;
429
430 r = selinux_create_file_prepare_abspath(abspath, mode);
431#endif
432 return r;
433}
434
435void mac_selinux_create_file_clear(void) {
436
437#if HAVE_SELINUX1
438 PROTECT_ERRNO__attribute__((cleanup(_reset_errno_))) __attribute__((unused
)) int _saved_errno_ = (*__errno_location ())
;
439
440 if (!mac_selinux_use())
441 return;
442
443 setfscreatecon_raw(NULL((void*)0));
444#endif
445}
446
447int mac_selinux_create_socket_prepare(const char *label) {
448
449#if HAVE_SELINUX1
450 if (!mac_selinux_use())
451 return 0;
452
453 assert(label)do { if ((__builtin_expect(!!(!(label)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("label"), "../src/basic/selinux-util.c",
453, __PRETTY_FUNCTION__); } while (0)
;
454
455 if (setsockcreatecon(label) < 0) {
456 log_enforcing_errno(errno, "Failed to set SELinux security context %s for sockets: %m", label)({ int _level = ((security_getenforce() == 1 ? 3 : 7)), _e = (
((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm
(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((
_realm) << 10 | (_level)), _e, "../src/basic/selinux-util.c"
, 456, __func__, "Failed to set SELinux security context %s for sockets: %m"
, label) : -abs(_e); })
;
457
458 if (security_getenforce() == 1)
459 return -errno(*__errno_location ());
460 }
461#endif
462
463 return 0;
464}
465
466void mac_selinux_create_socket_clear(void) {
467
468#if HAVE_SELINUX1
469 PROTECT_ERRNO__attribute__((cleanup(_reset_errno_))) __attribute__((unused
)) int _saved_errno_ = (*__errno_location ())
;
470
471 if (!mac_selinux_use())
472 return;
473
474 setsockcreatecon_raw(NULL((void*)0));
475#endif
476}
477
478int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
479
480 /* Binds a socket and label its file system object according to the SELinux policy */
481
482#if HAVE_SELINUX1
483 _cleanup_freecon___attribute__((cleanup(freeconp))) char *fcon = NULL((void*)0);
484 const struct sockaddr_un *un;
485 bool_Bool context_changed = false0;
486 char *path;
487 int r;
488
489 assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/basic/selinux-util.c"
, 489, __PRETTY_FUNCTION__); } while (0)
;
490 assert(addr)do { if ((__builtin_expect(!!(!(addr)),0))) log_assert_failed_realm
(LOG_REALM_SYSTEMD, ("addr"), "../src/basic/selinux-util.c", 490
, __PRETTY_FUNCTION__); } while (0)
;
491 assert(addrlen >= sizeof(sa_family_t))do { if ((__builtin_expect(!!(!(addrlen >= sizeof(sa_family_t
))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("addrlen >= sizeof(sa_family_t)"
), "../src/basic/selinux-util.c", 491, __PRETTY_FUNCTION__); }
while (0)
;
492
493 if (!label_hnd)
494 goto skipped;
495
496 /* Filter out non-local sockets */
497 if (addr->sa_family != AF_UNIX1)
498 goto skipped;
499
500 /* Filter out anonymous sockets */
501 if (addrlen < offsetof(struct sockaddr_un, sun_path)__builtin_offsetof(struct sockaddr_un, sun_path) + 1)
502 goto skipped;
503
504 /* Filter out abstract namespace sockets */
505 un = (const struct sockaddr_un*) addr;
506 if (un->sun_path[0] == 0)
507 goto skipped;
508
509 path = strndupa(un->sun_path, addrlen - offsetof(struct sockaddr_un, sun_path))(__extension__ ({ const char *__old = (un->sun_path); size_t
__len = strnlen (__old, (addrlen - __builtin_offsetof(struct
sockaddr_un, sun_path))); char *__new = (char *) __builtin_alloca
(__len + 1); __new[__len] = '\0'; (char *) memcpy (__new, __old
, __len); }))
;
510
511 /* Check for policy reload so 'label_hnd' is kept up-to-date by callbacks */
512 (void) avc_netlink_check_nb();
513
514 if (path_is_absolute(path))
515 r = selabel_lookup_raw(label_hnd, &fcon, path, S_IFSOCK0140000);
516 else {
517 _cleanup_free___attribute__((cleanup(freep))) char *newpath = NULL((void*)0);
518
519 r = path_make_absolute_cwd(path, &newpath);
520 if (r < 0)
521 return r;
522
523 r = selabel_lookup_raw(label_hnd, &fcon, newpath, S_IFSOCK0140000);
524 }
525
526 if (r < 0) {
527 /* No context specified by the policy? Proceed without setting it */
528 if (errno(*__errno_location ()) == ENOENT2)
529 goto skipped;
530
531 log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", path)({ int _level = ((security_getenforce() == 1 ? 3 : 7)), _e = (
((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm
(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((
_realm) << 10 | (_level)), _e, "../src/basic/selinux-util.c"
, 531, __func__, "Failed to determine SELinux security context for %s: %m"
, path) : -abs(_e); })
;
532 if (security_getenforce() > 0)
533 return -errno(*__errno_location ());
534
535 } else {
536 if (setfscreatecon_raw(fcon) < 0) {
537 log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", fcon, path)({ int _level = ((security_getenforce() == 1 ? 3 : 7)), _e = (
((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm
(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((
_realm) << 10 | (_level)), _e, "../src/basic/selinux-util.c"
, 537, __func__, "Failed to set SELinux security context %s for %s: %m"
, fcon, path) : -abs(_e); })
;
538 if (security_getenforce() > 0)
539 return -errno(*__errno_location ());
540 } else
541 context_changed = true1;
542 }
543
544 r = bind(fd, addr, addrlen) < 0 ? -errno(*__errno_location ()) : 0;
545
546 if (context_changed)
547 setfscreatecon_raw(NULL((void*)0));
548
549 return r;
550
551skipped:
552#endif
553 if (bind(fd, addr, addrlen) < 0)
554 return -errno(*__errno_location ());
555
556 return 0;
557}