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 WARN_ON(!mutex_is_locked(&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 91 kfree(state_str); 92 93 /* 94 * Measure SELinux policy only after initialization is completed. 95 */ 96 if (!selinux_initialized(state)) 97 return; 98 99 rc = security_read_state_kernel(state, &policy, &policy_len); 100 if (rc) { 101 pr_err("SELinux: %s: failed to read policy %d.\n", __func__, rc); 102 return; 103 } 104 105 ima_measure_critical_data("selinux", "selinux-policy-hash", 106 policy, policy_len, true); 107 108 vfree(policy); 109 } 110 111 /* 112 * selinux_ima_measure_state - Measure SELinux state and hash of policy 113 * 114 * @state: selinux state struct 115 */ 116 void selinux_ima_measure_state(struct selinux_state *state) 117 { 118 WARN_ON(mutex_is_locked(&state->policy_mutex)); 119 120 mutex_lock(&state->policy_mutex); 121 selinux_ima_measure_state_locked(state); 122 mutex_unlock(&state->policy_mutex); 123 } 124