]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
c4dcdb9f | 2 | |
07630cea | 3 | #include <unistd.h> |
c4dcdb9f | 4 | |
ad5db940 OJ |
5 | #include "sd-messages.h" |
6 | ||
ec888284 | 7 | #include "errno-util.h" |
baa6a42d | 8 | #include "initrd-util.h" |
07630cea | 9 | #include "log.h" |
cf0fbc49 | 10 | #include "selinux-setup.h" |
07630cea LP |
11 | #include "selinux-util.h" |
12 | #include "string-util.h" | |
ca78ad1d | 13 | #include "time-util.h" |
0b3325e7 | 14 | |
8a188de9 | 15 | int mac_selinux_setup(bool *loaded_policy) { |
ec888284 | 16 | assert(loaded_policy); |
c4dcdb9f | 17 | |
349cc4a5 | 18 | #if HAVE_SELINUX |
4ab72d6f | 19 | int r; |
4ab72d6f | 20 | |
d04f6fe4 | 21 | mac_selinux_disable_logging(); |
4ab72d6f | 22 | |
4a69c2c7 LP |
23 | /* Don't load policy in the initrd if we don't appear to have it. For the real root, we check below |
24 | * if we've already loaded policy, and return gracefully. */ | |
ec888284 LP |
25 | if (in_initrd() && access(selinux_path(), F_OK) < 0) { |
26 | if (errno != ENOENT) | |
27 | log_warning_errno(errno, "Unable to check if %s exists, assuming it does not: %m", selinux_path()); | |
28 | ||
4ab72d6f | 29 | return 0; |
ec888284 | 30 | } |
4ab72d6f | 31 | |
ec888284 LP |
32 | bool initialized = false; |
33 | ||
34 | /* Already initialized by somebody else? | |
35 | * | |
36 | * Note: getcon_raw() can return 0, and still give us a NULL pointer if /proc/self/attr/current is | |
4a69c2c7 LP |
37 | * empty. SELinux guarantees this won't happen, but that file isn't specific to SELinux, and may be |
38 | * provided by some other arbitrary LSM with different semantics. */ | |
ec888284 LP |
39 | _cleanup_freecon_ char *con = NULL; |
40 | if (getcon_raw(&con) < 0) | |
41 | log_debug_errno(errno, "getcon_raw() failed, assuming SELinux is not initialized: %m"); | |
42 | else if (con) { | |
4ab72d6f | 43 | initialized = !streq(con, "kernel"); |
ec888284 LP |
44 | log_debug("SELinux already initialized: %s", yes_no(initialized)); |
45 | } | |
4ab72d6f | 46 | |
ec888284 | 47 | /* Make sure we have no fds open while loading the policy and transitioning */ |
4ab72d6f WW |
48 | log_close(); |
49 | ||
50 | /* Now load the policy */ | |
ec888284 LP |
51 | usec_t before_load = now(CLOCK_MONOTONIC); |
52 | int enforce = 0; | |
53 | if (selinux_init_load_policy(&enforce) == 0) { /* NB: Apparently doesn't set useful errno! */ | |
6baa7db0 | 54 | mac_selinux_retest(); |
4ab72d6f WW |
55 | |
56 | /* Transition to the new context */ | |
ec888284 | 57 | _cleanup_freecon_ char *label = NULL; |
cc56fafe | 58 | r = mac_selinux_get_create_label_from_exe(SYSTEMD_BINARY_PATH, &label); |
ec888284 | 59 | if (r < 0) { |
4ab72d6f | 60 | log_open(); |
ec888284 | 61 | log_warning_errno(r, "Failed to compute init label, ignoring: %m"); |
4ab72d6f | 62 | } else { |
ec888284 | 63 | r = RET_NERRNO(setcon_raw(label)); |
4ab72d6f WW |
64 | log_open(); |
65 | if (r < 0) | |
ec888284 LP |
66 | log_warning_errno(r, "Failed to transition into init label '%s', ignoring: %m", label); |
67 | else | |
68 | log_debug("Successfully switched to calculated init label '%s'.", label); | |
4ab72d6f WW |
69 | } |
70 | ||
ec888284 | 71 | usec_t after_load = now(CLOCK_MONOTONIC); |
4ab72d6f | 72 | log_info("Successfully loaded SELinux policy in %s.", |
5291f26d | 73 | FORMAT_TIMESPAN(after_load - before_load, 0)); |
4ab72d6f WW |
74 | |
75 | *loaded_policy = true; | |
4ab72d6f WW |
76 | } else { |
77 | log_open(); | |
78 | ||
79 | if (enforce > 0) { | |
d7a0f1f4 | 80 | if (!initialized) |
ad5db940 OJ |
81 | return log_struct_errno(LOG_EMERG, SYNTHETIC_ERRNO(EIO), |
82 | LOG_MESSAGE("Failed to load SELinux policy :%m"), | |
3cf6a3a3 | 83 | LOG_MESSAGE_ID(SD_MESSAGE_SELINUX_FAILED_STR)); |
68d3acac | 84 | |
ec888284 | 85 | log_notice("Failed to load new SELinux policy. Continuing with old policy."); |
4ab72d6f WW |
86 | } else |
87 | log_debug("Unable to load SELinux policy. Ignoring."); | |
88 | } | |
c4dcdb9f LP |
89 | #endif |
90 | ||
4ab72d6f | 91 | return 0; |
c4dcdb9f | 92 | } |