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