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 maintained 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 * On success returns the configuration settings string. 19 * On error, returns NULL. 20 */ 21 static char *selinux_ima_collect_state(void) 22 { 23 const char *on = "=1;", *off = "=0;"; 24 char *buf; 25 int buf_len, len, i, rc; 26 27 buf_len = strlen("initialized=0;enforcing=0;checkreqprot=0;") + 1; 28 29 len = strlen(on); 30 for (i = 0; i < __POLICYDB_CAP_MAX; i++) 31 buf_len += strlen(selinux_policycap_names[i]) + len; 32 33 buf = kzalloc(buf_len, GFP_KERNEL); 34 if (!buf) 35 return NULL; 36 37 rc = strscpy(buf, "initialized", buf_len); 38 WARN_ON(rc < 0); 39 40 rc = strlcat(buf, selinux_initialized() ? on : off, buf_len); 41 WARN_ON(rc >= buf_len); 42 43 rc = strlcat(buf, "enforcing", buf_len); 44 WARN_ON(rc >= buf_len); 45 46 rc = strlcat(buf, enforcing_enabled() ? on : off, buf_len); 47 WARN_ON(rc >= buf_len); 48 49 rc = strlcat(buf, "checkreqprot", buf_len); 50 WARN_ON(rc >= buf_len); 51 52 rc = strlcat(buf, checkreqprot_get() ? on : off, buf_len); 53 WARN_ON(rc >= buf_len); 54 55 for (i = 0; i < __POLICYDB_CAP_MAX; i++) { 56 rc = strlcat(buf, selinux_policycap_names[i], buf_len); 57 WARN_ON(rc >= buf_len); 58 59 rc = strlcat(buf, selinux_state.policycap[i] ? on : off, 60 buf_len); 61 WARN_ON(rc >= buf_len); 62 } 63 64 return buf; 65 } 66 67 /* 68 * selinux_ima_measure_state_locked - Measure SELinux state and hash of policy 69 */ 70 void selinux_ima_measure_state_locked(void) 71 { 72 char *state_str = NULL; 73 void *policy = NULL; 74 size_t policy_len; 75 int rc = 0; 76 77 lockdep_assert_held(&selinux_state.policy_mutex); 78 79 state_str = selinux_ima_collect_state(); 80 if (!state_str) { 81 pr_err("SELinux: %s: failed to read state.\n", __func__); 82 return; 83 } 84 85 ima_measure_critical_data("selinux", "selinux-state", 86 state_str, strlen(state_str), false, 87 NULL, 0); 88 89 kfree(state_str); 90 91 /* 92 * Measure SELinux policy only after initialization is completed. 93 */ 94 if (!selinux_initialized()) 95 return; 96 97 rc = security_read_state_kernel(&policy, &policy_len); 98 if (rc) { 99 pr_err("SELinux: %s: failed to read policy %d.\n", __func__, rc); 100 return; 101 } 102 103 ima_measure_critical_data("selinux", "selinux-policy-hash", 104 policy, policy_len, true, 105 NULL, 0); 106 107 vfree(policy); 108 } 109 110 /* 111 * selinux_ima_measure_state - Measure SELinux state and hash of policy 112 */ 113 void selinux_ima_measure_state(void) 114 { 115 lockdep_assert_not_held(&selinux_state.policy_mutex); 116 117 mutex_lock(&selinux_state.policy_mutex); 118 selinux_ima_measure_state_locked(); 119 mutex_unlock(&selinux_state.policy_mutex); 120 } 121