1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2021 Microsoft Corporation 4 * 5 * Author: Lakshmi Ramasubramanian (nramas@linux.microsoft.com) 6 * 7 * Measure critical data structures maintainted by SELinux 8 * using IMA subsystem. 9 */ 10 #include <linux/vmalloc.h> 11 #include <linux/ima.h> 12 #include "security.h" 13 #include "ima.h" 14 15 /* 16 * selinux_ima_collect_state - Read selinux configuration settings 17 * 18 * @state: selinux_state 19 * 20 * On success returns the configuration settings string. 21 * On error, returns NULL. 22 */ 23 static char *selinux_ima_collect_state(struct selinux_state *state) 24 { 25 const char *on = "=1;", *off = "=0;"; 26 char *buf; 27 int buf_len, len, i, rc; 28 29 buf_len = strlen("initialized=0;enforcing=0;checkreqprot=0;") + 1; 30 31 len = strlen(on); 32 for (i = 0; i < __POLICYDB_CAPABILITY_MAX; i++) 33 buf_len += strlen(selinux_policycap_names[i]) + len; 34 35 buf = kzalloc(buf_len, GFP_KERNEL); 36 if (!buf) 37 return NULL; 38 39 rc = strscpy(buf, "initialized", buf_len); 40 WARN_ON(rc < 0); 41 42 rc = strlcat(buf, selinux_initialized(state) ? on : off, buf_len); 43 WARN_ON(rc >= buf_len); 44 45 rc = strlcat(buf, "enforcing", buf_len); 46 WARN_ON(rc >= buf_len); 47 48 rc = strlcat(buf, enforcing_enabled(state) ? on : off, buf_len); 49 WARN_ON(rc >= buf_len); 50 51 rc = strlcat(buf, "checkreqprot", buf_len); 52 WARN_ON(rc >= buf_len); 53 54 rc = strlcat(buf, checkreqprot_get(state) ? on : off, buf_len); 55 WARN_ON(rc >= buf_len); 56 57 for (i = 0; i < __POLICYDB_CAPABILITY_MAX; i++) { 58 rc = strlcat(buf, selinux_policycap_names[i], buf_len); 59 WARN_ON(rc >= buf_len); 60 61 rc = strlcat(buf, state->policycap[i] ? on : off, buf_len); 62 WARN_ON(rc >= buf_len); 63 } 64 65 return buf; 66 } 67 68 /* 69 * selinux_ima_measure_state_locked - Measure SELinux state and hash of policy 70 * 71 * @state: selinux state struct 72 */ 73 void selinux_ima_measure_state_locked(struct selinux_state *state) 74 { 75 char *state_str = NULL; 76 void *policy = NULL; 77 size_t policy_len; 78 int rc = 0; 79 80 lockdep_assert_held(&state->policy_mutex); 81 82 state_str = selinux_ima_collect_state(state); 83 if (!state_str) { 84 pr_err("SELinux: %s: failed to read state.\n", __func__); 85 return; 86 } 87 88 ima_measure_critical_data("selinux", "selinux-state", 89 state_str, strlen(state_str), false, 90 NULL, 0); 91 92 kfree(state_str); 93 94 /* 95 * Measure SELinux policy only after initialization is completed. 96 */ 97 if (!selinux_initialized(state)) 98 return; 99 100 rc = security_read_state_kernel(state, &policy, &policy_len); 101 if (rc) { 102 pr_err("SELinux: %s: failed to read policy %d.\n", __func__, rc); 103 return; 104 } 105 106 ima_measure_critical_data("selinux", "selinux-policy-hash", 107 policy, policy_len, true, 108 NULL, 0); 109 110 vfree(policy); 111 } 112 113 /* 114 * selinux_ima_measure_state - Measure SELinux state and hash of policy 115 * 116 * @state: selinux state struct 117 */ 118 void selinux_ima_measure_state(struct selinux_state *state) 119 { 120 lockdep_assert_not_held(&state->policy_mutex); 121 122 mutex_lock(&state->policy_mutex); 123 selinux_ima_measure_state_locked(state); 124 mutex_unlock(&state->policy_mutex); 125 } 126