]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/selinux-util.c
hostnamectl: fix hyperlink in "Operating System" field
[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
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
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();
7960ba96
ZJS
275 if (!label_hnd)
276 return 0;
61f3e897 277
c3151977 278 if (selabel_lookup_raw(label_hnd, &fcon, inside_path, st.st_mode) < 0) {
66b6d9d5 279 /* If there's no label to set, then exit without warning */
9271daee 280 if (errno == ENOENT)
66b6d9d5
WC
281 return 0;
282
9271daee 283 r = -errno;
08c84981 284 goto fail;
66b6d9d5
WC
285 }
286
08c84981
LP
287 xsprintf(procfs_path, "/proc/self/fd/%i", fd);
288 if (setfilecon_raw(procfs_path, fcon) < 0) {
289 _cleanup_freecon_ char *oldcon = NULL;
290
08c84981 291 /* If the FS doesn't support labels, then exit without warning */
9271daee 292 if (ERRNO_IS_NOT_SUPPORTED(errno))
66b6d9d5
WC
293 return 0;
294
08c84981 295 /* It the FS is read-only and we were told to ignore failures caused by that, suppress error */
9271daee 296 if (errno == EROFS && (flags & LABEL_IGNORE_EROFS))
66b6d9d5
WC
297 return 0;
298
9271daee
LP
299 r = -errno;
300
08c84981
LP
301 /* If the old label is identical to the new one, suppress any kind of error */
302 if (getfilecon_raw(procfs_path, &oldcon) >= 0 && streq(fcon, oldcon))
303 return 0;
304
305 goto fail;
66b6d9d5 306 }
08c84981
LP
307
308 return 0;
309
310fail:
9271daee 311 return log_enforcing_errno(r, "Unable to fix SELinux security context of %s (%s): %m", strna(path), strna(inside_path));
66b6d9d5
WC
312#endif
313
ecabcf8b 314 return 0;
66b6d9d5
WC
315}
316
ecabcf8b 317int mac_selinux_apply(const char *path, const char *label) {
66b6d9d5 318
9271daee
LP
319 assert(path);
320
349cc4a5 321#if HAVE_SELINUX
ecabcf8b
LP
322 if (!mac_selinux_use())
323 return 0;
324
0f474365
LP
325 assert(label);
326
65804d6a
LP
327 if (setfilecon(path, label) < 0)
328 return log_enforcing_errno(errno, "Failed to set SELinux security context %s on path %s: %m", label, path);
66b6d9d5 329#endif
ecabcf8b 330 return 0;
d682b3a7
LP
331}
332
9271daee
LP
333int mac_selinux_apply_fd(int fd, const char *path, const char *label) {
334
335 assert(fd >= 0);
336
337#if HAVE_SELINUX
338 if (!mac_selinux_use())
339 return 0;
340
341 assert(label);
342
343 if (fsetfilecon(fd, label) < 0)
344 return log_enforcing_errno(errno, "Failed to set SELinux security context %s on path %s: %m", label, strna(path));
345#endif
346 return 0;
347}
348
cc56fafe 349int mac_selinux_get_create_label_from_exe(const char *exe, char **label) {
349cc4a5 350#if HAVE_SELINUX
2ed96880 351 _cleanup_freecon_ char *mycon = NULL, *fcon = NULL;
66b6d9d5 352 security_class_t sclass;
65804d6a 353 int r;
66b6d9d5 354
7f416dae
LP
355 assert(exe);
356 assert(label);
357
6d395665 358 if (!mac_selinux_use())
7f416dae 359 return -EOPNOTSUPP;
66b6d9d5 360
24154879 361 r = getcon_raw(&mycon);
66b6d9d5 362 if (r < 0)
7f416dae 363 return -errno;
66b6d9d5 364
24154879 365 r = getfilecon_raw(exe, &fcon);
66b6d9d5 366 if (r < 0)
7f416dae 367 return -errno;
66b6d9d5
WC
368
369 sclass = string_to_security_class("process");
fdb0405e
CG
370 if (sclass == 0)
371 return -ENOSYS;
372
2ed96880 373 r = security_compute_create_raw(mycon, fcon, sclass, label);
7f416dae
LP
374 if (r < 0)
375 return -errno;
66b6d9d5 376
65804d6a
LP
377 return 0;
378#else
379 return -EOPNOTSUPP;
380#endif
66b6d9d5
WC
381}
382
cc56fafe 383int mac_selinux_get_our_label(char **label) {
65804d6a
LP
384#if HAVE_SELINUX
385 int r;
66b6d9d5 386
7f416dae
LP
387 assert(label);
388
6d395665 389 if (!mac_selinux_use())
7f416dae 390 return -EOPNOTSUPP;
66b6d9d5 391
24154879 392 r = getcon_raw(label);
66b6d9d5 393 if (r < 0)
7f416dae 394 return -errno;
66b6d9d5 395
65804d6a
LP
396 return 0;
397#else
398 return -EOPNOTSUPP;
399#endif
66b6d9d5
WC
400}
401
9008e1ac 402int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *exec_label, char **label) {
349cc4a5 403#if HAVE_SELINUX
2ed96880 404 _cleanup_freecon_ char *mycon = NULL, *peercon = NULL, *fcon = NULL;
66b6d9d5
WC
405 _cleanup_context_free_ context_t pcon = NULL, bcon = NULL;
406 security_class_t sclass;
66b6d9d5 407 const char *range = NULL;
65804d6a 408 int r;
66b6d9d5
WC
409
410 assert(socket_fd >= 0);
411 assert(exe);
412 assert(label);
413
6d395665 414 if (!mac_selinux_use())
7f416dae
LP
415 return -EOPNOTSUPP;
416
24154879 417 r = getcon_raw(&mycon);
7f416dae
LP
418 if (r < 0)
419 return -errno;
66b6d9d5 420
a1d2de07 421 r = getpeercon_raw(socket_fd, &peercon);
7f416dae
LP
422 if (r < 0)
423 return -errno;
66b6d9d5 424
9008e1ac 425 if (!exec_label) {
66b6d9d5
WC
426 /* If there is no context set for next exec let's use context
427 of target executable */
24154879 428 r = getfilecon_raw(exe, &fcon);
7f416dae
LP
429 if (r < 0)
430 return -errno;
66b6d9d5
WC
431 }
432
433 bcon = context_new(mycon);
7f416dae
LP
434 if (!bcon)
435 return -ENOMEM;
66b6d9d5
WC
436
437 pcon = context_new(peercon);
7f416dae
LP
438 if (!pcon)
439 return -ENOMEM;
66b6d9d5
WC
440
441 range = context_range_get(pcon);
7f416dae
LP
442 if (!range)
443 return -errno;
66b6d9d5
WC
444
445 r = context_range_set(bcon, range);
7f416dae
LP
446 if (r)
447 return -errno;
66b6d9d5
WC
448
449 freecon(mycon);
450 mycon = strdup(context_str(bcon));
7f416dae
LP
451 if (!mycon)
452 return -ENOMEM;
66b6d9d5
WC
453
454 sclass = string_to_security_class("process");
fdb0405e
CG
455 if (sclass == 0)
456 return -ENOSYS;
457
2ed96880 458 r = security_compute_create_raw(mycon, fcon, sclass, label);
7f416dae
LP
459 if (r < 0)
460 return -errno;
7f416dae 461
65804d6a
LP
462 return 0;
463#else
464 return -EOPNOTSUPP;
465#endif
66b6d9d5
WC
466}
467
710a6b50 468char* mac_selinux_free(char *label) {
ecabcf8b 469
349cc4a5 470#if HAVE_SELINUX
2ed96880 471 freecon(label);
3d9fbea4
CG
472#else
473 assert(!label);
ecabcf8b 474#endif
710a6b50
LP
475
476 return NULL;
ecabcf8b
LP
477}
478
349cc4a5 479#if HAVE_SELINUX
7e531a52 480static int selinux_create_file_prepare_abspath(const char *abspath, mode_t mode) {
2ed96880 481 _cleanup_freecon_ char *filecon = NULL;
0f474365 482 int r;
66b6d9d5 483
7e531a52
FB
484 assert(abspath);
485 assert(path_is_absolute(abspath));
c34255bd 486
61f3e897 487 /* Check for policy reload so 'label_hnd' is kept up-to-date by callbacks */
fd5e402f 488 mac_selinux_maybe_reload();
7960ba96
ZJS
489 if (!label_hnd)
490 return 0;
61f3e897 491
7e531a52 492 r = selabel_lookup_raw(label_hnd, &filecon, abspath, mode);
0f474365
LP
493 if (r < 0) {
494 /* No context specified by the policy? Proceed without setting it. */
495 if (errno == ENOENT)
496 return 0;
2d58aa46 497
65804d6a 498 return log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", abspath);
66b6d9d5
WC
499 }
500
65804d6a
LP
501 if (setfscreatecon_raw(filecon) < 0)
502 return log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", filecon, abspath);
66b6d9d5 503
0f474365 504 return 0;
66b6d9d5 505}
7e531a52
FB
506#endif
507
508int mac_selinux_create_file_prepare_at(int dirfd, const char *path, mode_t mode) {
7e531a52
FB
509#if HAVE_SELINUX
510 _cleanup_free_ char *abspath = NULL;
65804d6a
LP
511 int r;
512
7e531a52
FB
513 assert(path);
514
515 if (!label_hnd)
516 return 0;
517
518 if (!path_is_absolute(path)) {
519 _cleanup_free_ char *p = NULL;
520
521 if (dirfd == AT_FDCWD)
522 r = safe_getcwd(&p);
523 else
524 r = fd_get_path(dirfd, &p);
525 if (r < 0)
526 return r;
527
62a85ee0 528 path = abspath = path_join(p, path);
30016f21 529 if (!path)
7e531a52 530 return -ENOMEM;
7e531a52
FB
531 }
532
65804d6a
LP
533 return selinux_create_file_prepare_abspath(path, mode);
534#else
535 return 0;
7e531a52 536#endif
7e531a52
FB
537}
538
539int mac_selinux_create_file_prepare(const char *path, mode_t mode) {
7e531a52 540#if HAVE_SELINUX
65804d6a
LP
541 int r;
542
7e531a52
FB
543 _cleanup_free_ char *abspath = NULL;
544
545 assert(path);
546
547 if (!label_hnd)
548 return 0;
549
550 r = path_make_absolute_cwd(path, &abspath);
551 if (r < 0)
552 return r;
553
65804d6a
LP
554 return selinux_create_file_prepare_abspath(abspath, mode);
555#else
556 return 0;
7e531a52 557#endif
7e531a52 558}
66b6d9d5 559
ecabcf8b 560void mac_selinux_create_file_clear(void) {
66b6d9d5 561
349cc4a5 562#if HAVE_SELINUX
66b6d9d5
WC
563 PROTECT_ERRNO;
564
6baa7db0 565 if (!mac_selinux_use())
66b6d9d5
WC
566 return;
567
a1d2de07 568 setfscreatecon_raw(NULL);
66b6d9d5
WC
569#endif
570}
571
ecabcf8b 572int mac_selinux_create_socket_prepare(const char *label) {
66b6d9d5 573
349cc4a5 574#if HAVE_SELINUX
ecabcf8b
LP
575 assert(label);
576
65804d6a
LP
577 if (!mac_selinux_use())
578 return 0;
ecabcf8b 579
65804d6a
LP
580 if (setsockcreatecon(label) < 0)
581 return log_enforcing_errno(errno, "Failed to set SELinux security context %s for sockets: %m", label);
66b6d9d5 582#endif
ecabcf8b
LP
583
584 return 0;
66b6d9d5
WC
585}
586
ecabcf8b 587void mac_selinux_create_socket_clear(void) {
66b6d9d5 588
349cc4a5 589#if HAVE_SELINUX
ecabcf8b
LP
590 PROTECT_ERRNO;
591
6baa7db0 592 if (!mac_selinux_use())
66b6d9d5
WC
593 return;
594
a1d2de07 595 setsockcreatecon_raw(NULL);
66b6d9d5
WC
596#endif
597}
598
cc56fafe 599int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
66b6d9d5
WC
600
601 /* Binds a socket and label its file system object according to the SELinux policy */
602
349cc4a5 603#if HAVE_SELINUX
2ed96880 604 _cleanup_freecon_ char *fcon = NULL;
66b6d9d5 605 const struct sockaddr_un *un;
0f474365 606 bool context_changed = false;
66b6d9d5
WC
607 char *path;
608 int r;
609
610 assert(fd >= 0);
611 assert(addr);
612 assert(addrlen >= sizeof(sa_family_t));
613
ecabcf8b 614 if (!label_hnd)
66b6d9d5
WC
615 goto skipped;
616
617 /* Filter out non-local sockets */
618 if (addr->sa_family != AF_UNIX)
619 goto skipped;
620
621 /* Filter out anonymous sockets */
0f474365 622 if (addrlen < offsetof(struct sockaddr_un, sun_path) + 1)
66b6d9d5
WC
623 goto skipped;
624
625 /* Filter out abstract namespace sockets */
626 un = (const struct sockaddr_un*) addr;
627 if (un->sun_path[0] == 0)
628 goto skipped;
629
630 path = strndupa(un->sun_path, addrlen - offsetof(struct sockaddr_un, sun_path));
631
61f3e897 632 /* Check for policy reload so 'label_hnd' is kept up-to-date by callbacks */
fd5e402f 633 mac_selinux_maybe_reload();
7960ba96
ZJS
634 if (!label_hnd)
635 goto skipped;
61f3e897 636
66b6d9d5
WC
637 if (path_is_absolute(path))
638 r = selabel_lookup_raw(label_hnd, &fcon, path, S_IFSOCK);
639 else {
0f474365 640 _cleanup_free_ char *newpath = NULL;
66b6d9d5 641
0f474365
LP
642 r = path_make_absolute_cwd(path, &newpath);
643 if (r < 0)
644 return r;
66b6d9d5
WC
645
646 r = selabel_lookup_raw(label_hnd, &fcon, newpath, S_IFSOCK);
647 }
648
0f474365
LP
649 if (r < 0) {
650 /* No context specified by the policy? Proceed without setting it */
651 if (errno == ENOENT)
652 goto skipped;
66b6d9d5 653
65804d6a
LP
654 r = log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", path);
655 if (r < 0)
656 return r;
0f474365 657 } else {
a1d2de07 658 if (setfscreatecon_raw(fcon) < 0) {
65804d6a
LP
659 r = log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", fcon, path);
660 if (r < 0)
661 return r;
0f474365
LP
662 } else
663 context_changed = true;
66b6d9d5
WC
664 }
665
0f474365
LP
666 r = bind(fd, addr, addrlen) < 0 ? -errno : 0;
667
668 if (context_changed)
65804d6a 669 (void) setfscreatecon_raw(NULL);
66b6d9d5 670
66b6d9d5
WC
671 return r;
672
673skipped:
674#endif
0f474365
LP
675 if (bind(fd, addr, addrlen) < 0)
676 return -errno;
677
678 return 0;
66b6d9d5 679}