Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */ 2 : : 3 : : #include <errno.h> 4 : : #include <stdio.h> 5 : : #include <unistd.h> 6 : : 7 : : #if HAVE_SELINUX 8 : : #include <selinux/selinux.h> 9 : : #endif 10 : : 11 : : #include "log.h" 12 : : #include "macro.h" 13 : : #include "selinux-setup.h" 14 : : #include "selinux-util.h" 15 : : #include "string-util.h" 16 : : #include "time-util.h" 17 : : #include "util.h" 18 : : 19 : : #if HAVE_SELINUX 20 : : _printf_(2,3) 21 : 0 : static int null_log(int type, const char *fmt, ...) { 22 : 0 : return 0; 23 : : } 24 : : #endif 25 : : 26 : 0 : int mac_selinux_setup(bool *loaded_policy) { 27 : : 28 : : #if HAVE_SELINUX 29 : 0 : int enforce = 0; 30 : : usec_t before_load, after_load; 31 : : char *con; 32 : : int r; 33 : : static const union selinux_callback cb = { 34 : : .func_log = null_log, 35 : : }; 36 : : 37 : 0 : bool initialized = false; 38 : : 39 [ # # ]: 0 : assert(loaded_policy); 40 : : 41 : : /* Turn off all of SELinux' own logging, we want to do that */ 42 : 0 : selinux_set_callback(SELINUX_CB_LOG, cb); 43 : : 44 : : /* Don't load policy in the initrd if we don't appear to have 45 : : * it. For the real root, we check below if we've already 46 : : * loaded policy, and return gracefully. 47 : : */ 48 [ # # # # ]: 0 : if (in_initrd() && access(selinux_path(), F_OK) < 0) 49 : 0 : return 0; 50 : : 51 : : /* Already initialized by somebody else? */ 52 : 0 : r = getcon_raw(&con); 53 [ # # ]: 0 : if (r == 0) { 54 : 0 : initialized = !streq(con, "kernel"); 55 : 0 : freecon(con); 56 : : } 57 : : 58 : : /* Make sure we have no fds open while loading the policy and 59 : : * transitioning */ 60 : 0 : log_close(); 61 : : 62 : : /* Now load the policy */ 63 : 0 : before_load = now(CLOCK_MONOTONIC); 64 : 0 : r = selinux_init_load_policy(&enforce); 65 [ # # ]: 0 : if (r == 0) { 66 : 0 : _cleanup_(mac_selinux_freep) char *label = NULL; 67 : : char timespan[FORMAT_TIMESPAN_MAX]; 68 : : 69 : 0 : mac_selinux_retest(); 70 : : 71 : : /* Transition to the new context */ 72 : 0 : r = mac_selinux_get_create_label_from_exe(SYSTEMD_BINARY_PATH, &label); 73 [ # # # # ]: 0 : if (r < 0 || !label) { 74 : 0 : log_open(); 75 [ # # ]: 0 : log_error("Failed to compute init label, ignoring."); 76 : : } else { 77 : 0 : r = setcon_raw(label); 78 : : 79 : 0 : log_open(); 80 [ # # ]: 0 : if (r < 0) 81 [ # # ]: 0 : log_error("Failed to transition into init label '%s', ignoring.", label); 82 : : } 83 : : 84 : 0 : after_load = now(CLOCK_MONOTONIC); 85 : : 86 [ # # ]: 0 : log_info("Successfully loaded SELinux policy in %s.", 87 : : format_timespan(timespan, sizeof(timespan), after_load - before_load, 0)); 88 : : 89 : 0 : *loaded_policy = true; 90 : : 91 : : } else { 92 : 0 : log_open(); 93 : : 94 [ # # ]: 0 : if (enforce > 0) { 95 [ # # ]: 0 : if (!initialized) { 96 [ # # ]: 0 : log_emergency("Failed to load SELinux policy."); 97 : 0 : return -EIO; 98 : : } 99 : : 100 [ # # ]: 0 : log_warning("Failed to load new SELinux policy. Continuing with old policy."); 101 : : } else 102 [ # # ]: 0 : log_debug("Unable to load SELinux policy. Ignoring."); 103 : : } 104 : : #endif 105 : : 106 : 0 : return 0; 107 : : }