xref: /linux/security/selinux/ima.c (revision 2f0f6b0773be0a1ec475097ae54848eea42adc7d)
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