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