]>
| 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 | |
| 83b6ef9b | 21 | r = dlopen_libselinux(); |
| 375a4bd8 MY |
22 | if (r < 0) { |
| 23 | log_debug_errno(r, "No SELinux library available, skipping setup."); | |
| 24 | return 0; | |
| 25 | } | |
| 83b6ef9b | 26 | |
| d04f6fe4 | 27 | mac_selinux_disable_logging(); |
| 4ab72d6f | 28 | |
| 4a69c2c7 LP |
29 | /* Don't load policy in the initrd if we don't appear to have it. For the real root, we check below |
| 30 | * if we've already loaded policy, and return gracefully. */ | |
| 83b6ef9b | 31 | if (in_initrd() && access(sym_selinux_path(), F_OK) < 0) { |
| ec888284 | 32 | if (errno != ENOENT) |
| 83b6ef9b | 33 | log_warning_errno(errno, "Unable to check if %s exists, assuming it does not: %m", sym_selinux_path()); |
| ec888284 | 34 | |
| 4ab72d6f | 35 | return 0; |
| ec888284 | 36 | } |
| 4ab72d6f | 37 | |
| ec888284 LP |
38 | bool initialized = false; |
| 39 | ||
| 40 | /* Already initialized by somebody else? | |
| 41 | * | |
| 42 | * Note: getcon_raw() can return 0, and still give us a NULL pointer if /proc/self/attr/current is | |
| 4a69c2c7 LP |
43 | * empty. SELinux guarantees this won't happen, but that file isn't specific to SELinux, and may be |
| 44 | * provided by some other arbitrary LSM with different semantics. */ | |
| ec888284 | 45 | _cleanup_freecon_ char *con = NULL; |
| 83b6ef9b | 46 | if (sym_getcon_raw(&con) < 0) |
| ec888284 LP |
47 | log_debug_errno(errno, "getcon_raw() failed, assuming SELinux is not initialized: %m"); |
| 48 | else if (con) { | |
| 4ab72d6f | 49 | initialized = !streq(con, "kernel"); |
| ec888284 LP |
50 | log_debug("SELinux already initialized: %s", yes_no(initialized)); |
| 51 | } | |
| 4ab72d6f | 52 | |
| ec888284 | 53 | /* Make sure we have no fds open while loading the policy and transitioning */ |
| 4ab72d6f WW |
54 | log_close(); |
| 55 | ||
| 56 | /* Now load the policy */ | |
| ec888284 LP |
57 | usec_t before_load = now(CLOCK_MONOTONIC); |
| 58 | int enforce = 0; | |
| 83b6ef9b | 59 | if (sym_selinux_init_load_policy(&enforce) == 0) { /* NB: Apparently doesn't set useful errno! */ |
| 6baa7db0 | 60 | mac_selinux_retest(); |
| 4ab72d6f WW |
61 | |
| 62 | /* Transition to the new context */ | |
| ec888284 | 63 | _cleanup_freecon_ char *label = NULL; |
| cc56fafe | 64 | r = mac_selinux_get_create_label_from_exe(SYSTEMD_BINARY_PATH, &label); |
| ec888284 | 65 | if (r < 0) { |
| 4ab72d6f | 66 | log_open(); |
| ec888284 | 67 | log_warning_errno(r, "Failed to compute init label, ignoring: %m"); |
| 4ab72d6f | 68 | } else { |
| 83b6ef9b | 69 | r = RET_NERRNO(sym_setcon_raw(label)); |
| 4ab72d6f WW |
70 | log_open(); |
| 71 | if (r < 0) | |
| ec888284 LP |
72 | log_warning_errno(r, "Failed to transition into init label '%s', ignoring: %m", label); |
| 73 | else | |
| 74 | log_debug("Successfully switched to calculated init label '%s'.", label); | |
| 4ab72d6f WW |
75 | } |
| 76 | ||
| ec888284 | 77 | usec_t after_load = now(CLOCK_MONOTONIC); |
| 4ab72d6f | 78 | log_info("Successfully loaded SELinux policy in %s.", |
| 5291f26d | 79 | FORMAT_TIMESPAN(after_load - before_load, 0)); |
| 4ab72d6f WW |
80 | |
| 81 | *loaded_policy = true; | |
| 4ab72d6f WW |
82 | } else { |
| 83 | log_open(); | |
| 84 | ||
| 85 | if (enforce > 0) { | |
| d7a0f1f4 | 86 | if (!initialized) |
| ad5db940 | 87 | return log_struct_errno(LOG_EMERG, SYNTHETIC_ERRNO(EIO), |
| 7f6086d5 | 88 | LOG_MESSAGE("Failed to load SELinux policy."), |
| 3cf6a3a3 | 89 | LOG_MESSAGE_ID(SD_MESSAGE_SELINUX_FAILED_STR)); |
| 68d3acac | 90 | |
| ec888284 | 91 | log_notice("Failed to load new SELinux policy. Continuing with old policy."); |
| 4ab72d6f WW |
92 | } else |
| 93 | log_debug("Unable to load SELinux policy. Ignoring."); | |
| 94 | } | |
| c4dcdb9f LP |
95 | #endif |
| 96 | ||
| 4ab72d6f | 97 | return 0; |
| c4dcdb9f | 98 | } |