]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/selinux-util.c
tree-wide: return NULL from freeing functions
[thirdparty/systemd.git] / src / basic / selinux-util.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
cad45ba1 2
66b6d9d5 3#include <errno.h>
ca78ad1d 4#include <fcntl.h>
66b6d9d5 5#include <malloc.h>
11c3a366
TA
6#include <stddef.h>
7#include <string.h>
8#include <sys/stat.h>
9#include <sys/time.h>
ca78ad1d 10#include <sys/types.h>
66b6d9d5 11#include <sys/un.h>
11c3a366 12#include <syslog.h>
a07e9cfb 13
349cc4a5 14#if HAVE_SELINUX
61f3e897 15#include <selinux/avc.h>
66b6d9d5 16#include <selinux/context.h>
cf0fbc49
TA
17#include <selinux/label.h>
18#include <selinux/selinux.h>
66b6d9d5
WC
19#endif
20
b5efdb8a 21#include "alloc-util.h"
2b2fec7d 22#include "errno-util.h"
08c84981 23#include "fd-util.h"
11c3a366
TA
24#include "log.h"
25#include "macro.h"
93cc7779
TA
26#include "path-util.h"
27#include "selinux-util.h"
08c84981 28#include "stdio-util.h"
11c3a366 29#include "time-util.h"
cad45ba1 30
349cc4a5 31#if HAVE_SELINUX
66b6d9d5 32DEFINE_TRIVIAL_CLEANUP_FUNC(context_t, context_free);
66b6d9d5 33#define _cleanup_context_free_ _cleanup_(context_freep)
0b6018f3 34
61f3e897
CG
35static int mac_selinux_reload(int seqno);
36
6baa7db0 37static int cached_use = -1;
fd5e402f
CG
38static bool initialized = false;
39static int (*enforcing_status_func)(void) = security_getenforce;
40static int last_policyload = 0;
66b6d9d5 41static struct selabel_handle *label_hnd = NULL;
66cedb30 42
3cd44590 43#define log_enforcing(...) \
fd5e402f 44 log_full(mac_selinux_enforcing() ? LOG_ERR : LOG_WARNING, __VA_ARGS__)
65804d6a
LP
45
46#define log_enforcing_errno(error, ...) \
47 ({ \
fd5e402f 48 bool _enforcing = mac_selinux_enforcing(); \
65804d6a
LP
49 int _level = _enforcing ? LOG_ERR : LOG_WARNING; \
50 int _e = (error); \
51 \
52 int _r = (log_get_max_level() >= LOG_PRI(_level)) \
10d296c1 53 ? log_internal(_level, _e, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \
65804d6a
LP
54 : -ERRNO_VALUE(_e); \
55 _enforcing ? _r : 0; \
56 })
66b6d9d5 57#endif
cad45ba1 58
6d395665 59bool mac_selinux_use(void) {
349cc4a5 60#if HAVE_SELINUX
2073bf3f 61 if (_unlikely_(cached_use < 0)) {
6baa7db0 62 cached_use = is_selinux_enabled() > 0;
2073bf3f
CG
63 log_debug("SELinux enabled state cached to: %s", cached_use ? "enabled" : "disabled");
64 }
cad45ba1 65
6baa7db0 66 return cached_use;
66b6d9d5
WC
67#else
68 return false;
69#endif
cad45ba1
LP
70}
71
fd5e402f
CG
72bool mac_selinux_enforcing(void) {
73#if HAVE_SELINUX
74 return enforcing_status_func() != 0;
75#else
76 return false;
77#endif
78}
79
6baa7db0 80void mac_selinux_retest(void) {
349cc4a5 81#if HAVE_SELINUX
6baa7db0 82 cached_use = -1;
66b6d9d5 83#endif
cad45ba1 84}
0b6018f3 85
349cc4a5 86#if HAVE_SELINUX
4b6f74f5
ZJS
87# if HAVE_MALLINFO
88static struct mallinfo mallinfo_nowarn(void) {
89 /* glibc has deprecated mallinfo(), but the replacement malloc_info() returns an XML blob ;=[ */
90DISABLE_WARNING_DEPRECATED_DECLARATIONS
91 return mallinfo();
92REENABLE_WARNING
93}
94# else
95# warning "mallinfo() is missing, add mallinfo2() supported instead."
96# endif
97
fd5e402f
CG
98static int open_label_db(void) {
99 struct selabel_handle *hnd;
66b6d9d5 100 usec_t before_timestamp, after_timestamp;
65804d6a 101 char timespan[FORMAT_TIMESPAN_MAX];
66b6d9d5 102
4b6f74f5
ZJS
103# if HAVE_MALLINFO
104 struct mallinfo before_mallinfo = mallinfo_nowarn();
105# endif
66b6d9d5
WC
106 before_timestamp = now(CLOCK_MONOTONIC);
107
fd5e402f
CG
108 hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
109 if (!hnd)
a9ba0e32 110 return log_enforcing_errno(errno, "Failed to initialize SELinux labeling handle: %m");
66b6d9d5 111
65804d6a 112 after_timestamp = now(CLOCK_MONOTONIC);
4b6f74f5
ZJS
113# if HAVE_MALLINFO
114 struct mallinfo after_mallinfo = mallinfo_nowarn();
115 int l = after_mallinfo.uordblks > before_mallinfo.uordblks ? after_mallinfo.uordblks - before_mallinfo.uordblks : 0;
65804d6a
LP
116 log_debug("Successfully loaded SELinux database in %s, size on heap is %iK.",
117 format_timespan(timespan, sizeof(timespan), after_timestamp - before_timestamp, 0),
4b6f74f5
ZJS
118 DIV_ROUND_UP(l, 1024));
119# else
120 log_debug("Successfully loaded SELinux database in %s.",
121 format_timespan(timespan, sizeof(timespan), after_timestamp - before_timestamp, 0));
122# endif
66b6d9d5 123
fd5e402f
CG
124 /* release memory after measurement */
125 if (label_hnd)
126 selabel_close(label_hnd);
127 label_hnd = TAKE_PTR(hnd);
128
129 return 0;
130}
131#endif
132
133int mac_selinux_init(void) {
134#if HAVE_SELINUX
135 int r;
961b341e 136 bool have_status_page = false;
fd5e402f
CG
137
138 if (initialized)
139 return 0;
140
141 if (!mac_selinux_use())
142 return 0;
143
961b341e
ZJS
144 r = selinux_status_open(/* netlink fallback */ 1);
145 if (r < 0) {
146 if (!ERRNO_IS_PRIVILEGE(errno))
147 return log_enforcing_errno(errno, "Failed to open SELinux status page: %m");
148 log_warning_errno(errno, "selinux_status_open() with netlink fallback failed, not checking for policy reloads: %m");
149 } else if (r == 1)
150 log_warning("selinux_status_open() failed to open the status page, using the netlink fallback.");
151 else
152 have_status_page = true;
fd5e402f
CG
153
154 r = open_label_db();
155 if (r < 0) {
156 selinux_status_close();
157 return r;
158 }
159
961b341e
ZJS
160 /* Save the current policyload sequence number, so mac_selinux_maybe_reload() does not trigger on
161 * first call without any actual change. */
fd5e402f
CG
162 last_policyload = selinux_status_policyload();
163
961b341e
ZJS
164 if (have_status_page)
165 /* Now that the SELinux status page has been successfully opened, retrieve the enforcing
166 * status over it (to avoid system calls in security_getenforce()). */
167 enforcing_status_func = selinux_status_getenforce;
fd5e402f
CG
168
169 initialized = true;
65804d6a
LP
170#endif
171 return 0;
d682b3a7
LP
172}
173
fd5e402f
CG
174void mac_selinux_maybe_reload(void) {
175#if HAVE_SELINUX
176 int r;
177
1006038c
CG
178 if (!initialized)
179 return;
180
fd5e402f
CG
181 r = selinux_status_updated();
182 if (r < 0)
183 log_debug_errno(errno, "Failed to update SELinux from status page: %m");
184 if (r > 0) {
185 int policyload;
186
187 log_debug("SELinux status page update");
188
189 /* from libselinux > 3.1 callbacks gets automatically called, see
190 https://github.com/SELinuxProject/selinux/commit/05bdc03130d741e53e1fb45a958d0a2c184be503 */
191
192 /* only reload on policy changes, not enforcing status changes */
193 policyload = selinux_status_policyload();
194 if (policyload != last_policyload) {
195 mac_selinux_reload(policyload);
196 last_policyload = policyload;
197 }
198 }
199#endif
200}
201
ecabcf8b
LP
202void mac_selinux_finish(void) {
203
349cc4a5 204#if HAVE_SELINUX
fd5e402f
CG
205 if (label_hnd) {
206 selabel_close(label_hnd);
207 label_hnd = NULL;
208 }
209
210 enforcing_status_func = security_getenforce;
ecabcf8b 211
fd5e402f
CG
212 selinux_status_close();
213
214 initialized = false;
ecabcf8b
LP
215#endif
216}
217
a9dfac21 218#if HAVE_SELINUX
61f3e897 219static int mac_selinux_reload(int seqno) {
fd5e402f 220 log_debug("SELinux reload %d", seqno);
a9dfac21 221
fd5e402f 222 (void) open_label_db();
61f3e897
CG
223
224 return 0;
a9dfac21 225}
61f3e897 226#endif
a9dfac21 227
c3151977 228int mac_selinux_fix_container(const char *path, const char *inside_path, LabelFixFlags flags) {
66b6d9d5 229
9271daee
LP
230 assert(path);
231 assert(inside_path);
232
349cc4a5 233#if HAVE_SELINUX
08c84981 234 _cleanup_close_ int fd = -1;
5dfc5461
LP
235
236 /* if mac_selinux_init() wasn't called before we are a NOOP */
66b6d9d5
WC
237 if (!label_hnd)
238 return 0;
239
08c84981
LP
240 /* Open the file as O_PATH, to pin it while we determine and adjust the label */
241 fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
242 if (fd < 0) {
243 if ((flags & LABEL_IGNORE_ENOENT) && errno == ENOENT)
244 return 0;
245
246 return -errno;
247 }
248
9271daee
LP
249 return mac_selinux_fix_container_fd(fd, path, inside_path, flags);
250#endif
251
252 return 0;
253}
254
255int mac_selinux_fix_container_fd(int fd, const char *path, const char *inside_path, LabelFixFlags flags) {
256
257 assert(fd >= 0);
258 assert(inside_path);
259
260#if HAVE_SELINUX
261 char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
262 _cleanup_freecon_ char* fcon = NULL;
263 struct stat st;
264 int r;
265
266 /* if mac_selinux_init() wasn't called before we are a NOOP */
267 if (!label_hnd)
268 return 0;
269
08c84981
LP
270 if (fstat(fd, &st) < 0)
271 return -errno;
5dfc5461 272
61f3e897 273 /* Check for policy reload so 'label_hnd' is kept up-to-date by callbacks */
fd5e402f 274 mac_selinux_maybe_reload();
61f3e897 275
c3151977 276 if (selabel_lookup_raw(label_hnd, &fcon, inside_path, st.st_mode) < 0) {
66b6d9d5 277 /* If there's no label to set, then exit without warning */
9271daee 278 if (errno == ENOENT)
66b6d9d5
WC
279 return 0;
280
9271daee 281 r = -errno;
08c84981 282 goto fail;
66b6d9d5
WC
283 }
284
08c84981
LP
285 xsprintf(procfs_path, "/proc/self/fd/%i", fd);
286 if (setfilecon_raw(procfs_path, fcon) < 0) {
287 _cleanup_freecon_ char *oldcon = NULL;
288
08c84981 289 /* If the FS doesn't support labels, then exit without warning */
9271daee 290 if (ERRNO_IS_NOT_SUPPORTED(errno))
66b6d9d5
WC
291 return 0;
292
08c84981 293 /* It the FS is read-only and we were told to ignore failures caused by that, suppress error */
9271daee 294 if (errno == EROFS && (flags & LABEL_IGNORE_EROFS))
66b6d9d5
WC
295 return 0;
296
9271daee
LP
297 r = -errno;
298
08c84981
LP
299 /* If the old label is identical to the new one, suppress any kind of error */
300 if (getfilecon_raw(procfs_path, &oldcon) >= 0 && streq(fcon, oldcon))
301 return 0;
302
303 goto fail;
66b6d9d5 304 }
08c84981
LP
305
306 return 0;
307
308fail:
9271daee 309 return log_enforcing_errno(r, "Unable to fix SELinux security context of %s (%s): %m", strna(path), strna(inside_path));
66b6d9d5
WC
310#endif
311
ecabcf8b 312 return 0;
66b6d9d5
WC
313}
314
ecabcf8b 315int mac_selinux_apply(const char *path, const char *label) {
66b6d9d5 316
9271daee
LP
317 assert(path);
318
349cc4a5 319#if HAVE_SELINUX
ecabcf8b
LP
320 if (!mac_selinux_use())
321 return 0;
322
0f474365
LP
323 assert(label);
324
65804d6a
LP
325 if (setfilecon(path, label) < 0)
326 return log_enforcing_errno(errno, "Failed to set SELinux security context %s on path %s: %m", label, path);
66b6d9d5 327#endif
ecabcf8b 328 return 0;
d682b3a7
LP
329}
330
9271daee
LP
331int mac_selinux_apply_fd(int fd, const char *path, const char *label) {
332
333 assert(fd >= 0);
334
335#if HAVE_SELINUX
336 if (!mac_selinux_use())
337 return 0;
338
339 assert(label);
340
341 if (fsetfilecon(fd, label) < 0)
342 return log_enforcing_errno(errno, "Failed to set SELinux security context %s on path %s: %m", label, strna(path));
343#endif
344 return 0;
345}
346
cc56fafe 347int mac_selinux_get_create_label_from_exe(const char *exe, char **label) {
349cc4a5 348#if HAVE_SELINUX
2ed96880 349 _cleanup_freecon_ char *mycon = NULL, *fcon = NULL;
66b6d9d5 350 security_class_t sclass;
65804d6a 351 int r;
66b6d9d5 352
7f416dae
LP
353 assert(exe);
354 assert(label);
355
6d395665 356 if (!mac_selinux_use())
7f416dae 357 return -EOPNOTSUPP;
66b6d9d5 358
24154879 359 r = getcon_raw(&mycon);
66b6d9d5 360 if (r < 0)
7f416dae 361 return -errno;
66b6d9d5 362
24154879 363 r = getfilecon_raw(exe, &fcon);
66b6d9d5 364 if (r < 0)
7f416dae 365 return -errno;
66b6d9d5
WC
366
367 sclass = string_to_security_class("process");
fdb0405e
CG
368 if (sclass == 0)
369 return -ENOSYS;
370
2ed96880 371 r = security_compute_create_raw(mycon, fcon, sclass, label);
7f416dae
LP
372 if (r < 0)
373 return -errno;
66b6d9d5 374
65804d6a
LP
375 return 0;
376#else
377 return -EOPNOTSUPP;
378#endif
66b6d9d5
WC
379}
380
cc56fafe 381int mac_selinux_get_our_label(char **label) {
65804d6a
LP
382#if HAVE_SELINUX
383 int r;
66b6d9d5 384
7f416dae
LP
385 assert(label);
386
6d395665 387 if (!mac_selinux_use())
7f416dae 388 return -EOPNOTSUPP;
66b6d9d5 389
24154879 390 r = getcon_raw(label);
66b6d9d5 391 if (r < 0)
7f416dae 392 return -errno;
66b6d9d5 393
65804d6a
LP
394 return 0;
395#else
396 return -EOPNOTSUPP;
397#endif
66b6d9d5
WC
398}
399
9008e1ac 400int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *exec_label, char **label) {
349cc4a5 401#if HAVE_SELINUX
2ed96880 402 _cleanup_freecon_ char *mycon = NULL, *peercon = NULL, *fcon = NULL;
66b6d9d5
WC
403 _cleanup_context_free_ context_t pcon = NULL, bcon = NULL;
404 security_class_t sclass;
66b6d9d5 405 const char *range = NULL;
65804d6a 406 int r;
66b6d9d5
WC
407
408 assert(socket_fd >= 0);
409 assert(exe);
410 assert(label);
411
6d395665 412 if (!mac_selinux_use())
7f416dae
LP
413 return -EOPNOTSUPP;
414
24154879 415 r = getcon_raw(&mycon);
7f416dae
LP
416 if (r < 0)
417 return -errno;
66b6d9d5 418
a1d2de07 419 r = getpeercon_raw(socket_fd, &peercon);
7f416dae
LP
420 if (r < 0)
421 return -errno;
66b6d9d5 422
9008e1ac 423 if (!exec_label) {
66b6d9d5
WC
424 /* If there is no context set for next exec let's use context
425 of target executable */
24154879 426 r = getfilecon_raw(exe, &fcon);
7f416dae
LP
427 if (r < 0)
428 return -errno;
66b6d9d5
WC
429 }
430
431 bcon = context_new(mycon);
7f416dae
LP
432 if (!bcon)
433 return -ENOMEM;
66b6d9d5
WC
434
435 pcon = context_new(peercon);
7f416dae
LP
436 if (!pcon)
437 return -ENOMEM;
66b6d9d5
WC
438
439 range = context_range_get(pcon);
7f416dae
LP
440 if (!range)
441 return -errno;
66b6d9d5
WC
442
443 r = context_range_set(bcon, range);
7f416dae
LP
444 if (r)
445 return -errno;
66b6d9d5
WC
446
447 freecon(mycon);
448 mycon = strdup(context_str(bcon));
7f416dae
LP
449 if (!mycon)
450 return -ENOMEM;
66b6d9d5
WC
451
452 sclass = string_to_security_class("process");
fdb0405e
CG
453 if (sclass == 0)
454 return -ENOSYS;
455
2ed96880 456 r = security_compute_create_raw(mycon, fcon, sclass, label);
7f416dae
LP
457 if (r < 0)
458 return -errno;
7f416dae 459
65804d6a
LP
460 return 0;
461#else
462 return -EOPNOTSUPP;
463#endif
66b6d9d5
WC
464}
465
710a6b50 466char* mac_selinux_free(char *label) {
ecabcf8b 467
349cc4a5 468#if HAVE_SELINUX
2ed96880 469 freecon(label);
3d9fbea4
CG
470#else
471 assert(!label);
ecabcf8b 472#endif
710a6b50
LP
473
474 return NULL;
ecabcf8b
LP
475}
476
349cc4a5 477#if HAVE_SELINUX
7e531a52 478static int selinux_create_file_prepare_abspath(const char *abspath, mode_t mode) {
2ed96880 479 _cleanup_freecon_ char *filecon = NULL;
0f474365 480 int r;
66b6d9d5 481
7e531a52
FB
482 assert(abspath);
483 assert(path_is_absolute(abspath));
c34255bd 484
61f3e897 485 /* Check for policy reload so 'label_hnd' is kept up-to-date by callbacks */
fd5e402f 486 mac_selinux_maybe_reload();
61f3e897 487
7e531a52 488 r = selabel_lookup_raw(label_hnd, &filecon, abspath, mode);
0f474365
LP
489 if (r < 0) {
490 /* No context specified by the policy? Proceed without setting it. */
491 if (errno == ENOENT)
492 return 0;
2d58aa46 493
65804d6a 494 return log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", abspath);
66b6d9d5
WC
495 }
496
65804d6a
LP
497 if (setfscreatecon_raw(filecon) < 0)
498 return log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", filecon, abspath);
66b6d9d5 499
0f474365 500 return 0;
66b6d9d5 501}
7e531a52
FB
502#endif
503
504int mac_selinux_create_file_prepare_at(int dirfd, const char *path, mode_t mode) {
7e531a52
FB
505#if HAVE_SELINUX
506 _cleanup_free_ char *abspath = NULL;
65804d6a
LP
507 int r;
508
7e531a52
FB
509
510 assert(path);
511
512 if (!label_hnd)
513 return 0;
514
515 if (!path_is_absolute(path)) {
516 _cleanup_free_ char *p = NULL;
517
518 if (dirfd == AT_FDCWD)
519 r = safe_getcwd(&p);
520 else
521 r = fd_get_path(dirfd, &p);
522 if (r < 0)
523 return r;
524
62a85ee0 525 path = abspath = path_join(p, path);
30016f21 526 if (!path)
7e531a52 527 return -ENOMEM;
7e531a52
FB
528 }
529
65804d6a
LP
530 return selinux_create_file_prepare_abspath(path, mode);
531#else
532 return 0;
7e531a52 533#endif
7e531a52
FB
534}
535
536int mac_selinux_create_file_prepare(const char *path, mode_t mode) {
7e531a52 537#if HAVE_SELINUX
65804d6a
LP
538 int r;
539
7e531a52
FB
540 _cleanup_free_ char *abspath = NULL;
541
542 assert(path);
543
544 if (!label_hnd)
545 return 0;
546
547 r = path_make_absolute_cwd(path, &abspath);
548 if (r < 0)
549 return r;
550
65804d6a
LP
551 return selinux_create_file_prepare_abspath(abspath, mode);
552#else
553 return 0;
7e531a52 554#endif
7e531a52 555}
66b6d9d5 556
ecabcf8b 557void mac_selinux_create_file_clear(void) {
66b6d9d5 558
349cc4a5 559#if HAVE_SELINUX
66b6d9d5
WC
560 PROTECT_ERRNO;
561
6baa7db0 562 if (!mac_selinux_use())
66b6d9d5
WC
563 return;
564
a1d2de07 565 setfscreatecon_raw(NULL);
66b6d9d5
WC
566#endif
567}
568
ecabcf8b 569int mac_selinux_create_socket_prepare(const char *label) {
66b6d9d5 570
349cc4a5 571#if HAVE_SELINUX
ecabcf8b
LP
572 assert(label);
573
65804d6a
LP
574 if (!mac_selinux_use())
575 return 0;
ecabcf8b 576
65804d6a
LP
577 if (setsockcreatecon(label) < 0)
578 return log_enforcing_errno(errno, "Failed to set SELinux security context %s for sockets: %m", label);
66b6d9d5 579#endif
ecabcf8b
LP
580
581 return 0;
66b6d9d5
WC
582}
583
ecabcf8b 584void mac_selinux_create_socket_clear(void) {
66b6d9d5 585
349cc4a5 586#if HAVE_SELINUX
ecabcf8b
LP
587 PROTECT_ERRNO;
588
6baa7db0 589 if (!mac_selinux_use())
66b6d9d5
WC
590 return;
591
a1d2de07 592 setsockcreatecon_raw(NULL);
66b6d9d5
WC
593#endif
594}
595
cc56fafe 596int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
66b6d9d5
WC
597
598 /* Binds a socket and label its file system object according to the SELinux policy */
599
349cc4a5 600#if HAVE_SELINUX
2ed96880 601 _cleanup_freecon_ char *fcon = NULL;
66b6d9d5 602 const struct sockaddr_un *un;
0f474365 603 bool context_changed = false;
66b6d9d5
WC
604 char *path;
605 int r;
606
607 assert(fd >= 0);
608 assert(addr);
609 assert(addrlen >= sizeof(sa_family_t));
610
ecabcf8b 611 if (!label_hnd)
66b6d9d5
WC
612 goto skipped;
613
614 /* Filter out non-local sockets */
615 if (addr->sa_family != AF_UNIX)
616 goto skipped;
617
618 /* Filter out anonymous sockets */
0f474365 619 if (addrlen < offsetof(struct sockaddr_un, sun_path) + 1)
66b6d9d5
WC
620 goto skipped;
621
622 /* Filter out abstract namespace sockets */
623 un = (const struct sockaddr_un*) addr;
624 if (un->sun_path[0] == 0)
625 goto skipped;
626
627 path = strndupa(un->sun_path, addrlen - offsetof(struct sockaddr_un, sun_path));
628
61f3e897 629 /* Check for policy reload so 'label_hnd' is kept up-to-date by callbacks */
fd5e402f 630 mac_selinux_maybe_reload();
61f3e897 631
66b6d9d5
WC
632 if (path_is_absolute(path))
633 r = selabel_lookup_raw(label_hnd, &fcon, path, S_IFSOCK);
634 else {
0f474365 635 _cleanup_free_ char *newpath = NULL;
66b6d9d5 636
0f474365
LP
637 r = path_make_absolute_cwd(path, &newpath);
638 if (r < 0)
639 return r;
66b6d9d5
WC
640
641 r = selabel_lookup_raw(label_hnd, &fcon, newpath, S_IFSOCK);
642 }
643
0f474365
LP
644 if (r < 0) {
645 /* No context specified by the policy? Proceed without setting it */
646 if (errno == ENOENT)
647 goto skipped;
66b6d9d5 648
65804d6a
LP
649 r = log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", path);
650 if (r < 0)
651 return r;
0f474365 652 } else {
a1d2de07 653 if (setfscreatecon_raw(fcon) < 0) {
65804d6a
LP
654 r = log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", fcon, path);
655 if (r < 0)
656 return r;
0f474365
LP
657 } else
658 context_changed = true;
66b6d9d5
WC
659 }
660
0f474365
LP
661 r = bind(fd, addr, addrlen) < 0 ? -errno : 0;
662
663 if (context_changed)
65804d6a 664 (void) setfscreatecon_raw(NULL);
66b6d9d5 665
66b6d9d5
WC
666 return r;
667
668skipped:
669#endif
0f474365
LP
670 if (bind(fd, addr, addrlen) < 0)
671 return -errno;
672
673 return 0;
66b6d9d5 674}