xref: /linux/security/ipe/audit.c (revision a68916eaedcd01f254ac4c09ca12b5065d710fd0)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved.
4  */
5 
6 #include <linux/slab.h>
7 #include <linux/audit.h>
8 #include <linux/types.h>
9 #include <crypto/hash.h>
10 
11 #include "ipe.h"
12 #include "eval.h"
13 #include "hooks.h"
14 #include "policy.h"
15 #include "audit.h"
16 
17 #define ACTSTR(x) ((x) == IPE_ACTION_ALLOW ? "ALLOW" : "DENY")
18 
19 #define IPE_AUDIT_HASH_ALG "sha256"
20 
21 #define AUDIT_POLICY_LOAD_FMT "policy_name=\"%s\" policy_version=%hu.%hu.%hu "\
22 			      "policy_digest=" IPE_AUDIT_HASH_ALG ":"
23 #define AUDIT_OLD_ACTIVE_POLICY_FMT "old_active_pol_name=\"%s\" "\
24 				    "old_active_pol_version=%hu.%hu.%hu "\
25 				    "old_policy_digest=" IPE_AUDIT_HASH_ALG ":"
26 #define AUDIT_OLD_ACTIVE_POLICY_NULL_FMT "old_active_pol_name=? "\
27 					 "old_active_pol_version=? "\
28 					 "old_policy_digest=?"
29 #define AUDIT_NEW_ACTIVE_POLICY_FMT "new_active_pol_name=\"%s\" "\
30 				    "new_active_pol_version=%hu.%hu.%hu "\
31 				    "new_policy_digest=" IPE_AUDIT_HASH_ALG ":"
32 
33 static const char *const audit_op_names[__IPE_OP_MAX + 1] = {
34 	"EXECUTE",
35 	"FIRMWARE",
36 	"KMODULE",
37 	"KEXEC_IMAGE",
38 	"KEXEC_INITRAMFS",
39 	"POLICY",
40 	"X509_CERT",
41 	"UNKNOWN",
42 };
43 
44 static const char *const audit_hook_names[__IPE_HOOK_MAX] = {
45 	"BPRM_CHECK",
46 	"MMAP",
47 	"MPROTECT",
48 	"KERNEL_READ",
49 	"KERNEL_LOAD",
50 };
51 
52 static const char *const audit_prop_names[__IPE_PROP_MAX] = {
53 	"boot_verified=FALSE",
54 	"boot_verified=TRUE",
55 };
56 
57 /**
58  * audit_rule() - audit an IPE policy rule.
59  * @ab: Supplies a pointer to the audit_buffer to append to.
60  * @r: Supplies a pointer to the ipe_rule to approximate a string form for.
61  */
62 static void audit_rule(struct audit_buffer *ab, const struct ipe_rule *r)
63 {
64 	const struct ipe_prop *ptr;
65 
66 	audit_log_format(ab, " rule=\"op=%s ", audit_op_names[r->op]);
67 
68 	list_for_each_entry(ptr, &r->props, next)
69 		audit_log_format(ab, "%s ", audit_prop_names[ptr->type]);
70 
71 	audit_log_format(ab, "action=%s\"", ACTSTR(r->action));
72 }
73 
74 /**
75  * ipe_audit_match() - Audit a rule match in a policy evaluation.
76  * @ctx: Supplies a pointer to the evaluation context that was used in the
77  *	 evaluation.
78  * @match_type: Supplies the scope of the match: rule, operation default,
79  *		global default.
80  * @act: Supplies the IPE's evaluation decision, deny or allow.
81  * @r: Supplies a pointer to the rule that was matched, if possible.
82  */
83 void ipe_audit_match(const struct ipe_eval_ctx *const ctx,
84 		     enum ipe_match match_type,
85 		     enum ipe_action_type act, const struct ipe_rule *const r)
86 {
87 	const char *op = audit_op_names[ctx->op];
88 	char comm[sizeof(current->comm)];
89 	struct audit_buffer *ab;
90 	struct inode *inode;
91 
92 	if (act != IPE_ACTION_DENY && !READ_ONCE(success_audit))
93 		return;
94 
95 	ab = audit_log_start(audit_context(), GFP_ATOMIC | __GFP_NOWARN,
96 			     AUDIT_IPE_ACCESS);
97 	if (!ab)
98 		return;
99 
100 	audit_log_format(ab, "ipe_op=%s ipe_hook=%s enforcing=%d pid=%d comm=",
101 			 op, audit_hook_names[ctx->hook], READ_ONCE(enforce),
102 			 task_tgid_nr(current));
103 	audit_log_untrustedstring(ab, get_task_comm(comm, current));
104 
105 	if (ctx->file) {
106 		audit_log_d_path(ab, " path=", &ctx->file->f_path);
107 		inode = file_inode(ctx->file);
108 		if (inode) {
109 			audit_log_format(ab, " dev=");
110 			audit_log_untrustedstring(ab, inode->i_sb->s_id);
111 			audit_log_format(ab, " ino=%lu", inode->i_ino);
112 		} else {
113 			audit_log_format(ab, " dev=? ino=?");
114 		}
115 	} else {
116 		audit_log_format(ab, " path=? dev=? ino=?");
117 	}
118 
119 	if (match_type == IPE_MATCH_RULE)
120 		audit_rule(ab, r);
121 	else if (match_type == IPE_MATCH_TABLE)
122 		audit_log_format(ab, " rule=\"DEFAULT op=%s action=%s\"", op,
123 				 ACTSTR(act));
124 	else
125 		audit_log_format(ab, " rule=\"DEFAULT action=%s\"",
126 				 ACTSTR(act));
127 
128 	audit_log_end(ab);
129 }
130 
131 /**
132  * audit_policy() - Audit a policy's name, version and thumbprint to @ab.
133  * @ab: Supplies a pointer to the audit buffer to append to.
134  * @audit_format: Supplies a pointer to the audit format string
135  * @p: Supplies a pointer to the policy to audit.
136  */
137 static void audit_policy(struct audit_buffer *ab,
138 			 const char *audit_format,
139 			 const struct ipe_policy *const p)
140 {
141 	SHASH_DESC_ON_STACK(desc, tfm);
142 	struct crypto_shash *tfm;
143 	u8 *digest = NULL;
144 
145 	tfm = crypto_alloc_shash(IPE_AUDIT_HASH_ALG, 0, 0);
146 	if (IS_ERR(tfm))
147 		return;
148 
149 	desc->tfm = tfm;
150 
151 	digest = kzalloc(crypto_shash_digestsize(tfm), GFP_KERNEL);
152 	if (!digest)
153 		goto out;
154 
155 	if (crypto_shash_init(desc))
156 		goto out;
157 
158 	if (crypto_shash_update(desc, p->pkcs7, p->pkcs7len))
159 		goto out;
160 
161 	if (crypto_shash_final(desc, digest))
162 		goto out;
163 
164 	audit_log_format(ab, audit_format, p->parsed->name,
165 			 p->parsed->version.major, p->parsed->version.minor,
166 			 p->parsed->version.rev);
167 	audit_log_n_hex(ab, digest, crypto_shash_digestsize(tfm));
168 
169 out:
170 	kfree(digest);
171 	crypto_free_shash(tfm);
172 }
173 
174 /**
175  * ipe_audit_policy_activation() - Audit a policy being activated.
176  * @op: Supplies a pointer to the previously activated policy to audit.
177  * @np: Supplies a pointer to the newly activated policy to audit.
178  */
179 void ipe_audit_policy_activation(const struct ipe_policy *const op,
180 				 const struct ipe_policy *const np)
181 {
182 	struct audit_buffer *ab;
183 
184 	ab = audit_log_start(audit_context(), GFP_KERNEL,
185 			     AUDIT_IPE_CONFIG_CHANGE);
186 	if (!ab)
187 		return;
188 
189 	if (op) {
190 		audit_policy(ab, AUDIT_OLD_ACTIVE_POLICY_FMT, op);
191 		audit_log_format(ab, " ");
192 	} else {
193 		/*
194 		 * old active policy can be NULL if there is no kernel
195 		 * built-in policy
196 		 */
197 		audit_log_format(ab, AUDIT_OLD_ACTIVE_POLICY_NULL_FMT);
198 		audit_log_format(ab, " ");
199 	}
200 	audit_policy(ab, AUDIT_NEW_ACTIVE_POLICY_FMT, np);
201 	audit_log_format(ab, " auid=%u ses=%u lsm=ipe res=1",
202 			 from_kuid(&init_user_ns, audit_get_loginuid(current)),
203 			 audit_get_sessionid(current));
204 
205 	audit_log_end(ab);
206 }
207 
208 /**
209  * ipe_audit_policy_load() - Audit a policy being loaded into the kernel.
210  * @p: Supplies a pointer to the policy to audit.
211  */
212 void ipe_audit_policy_load(const struct ipe_policy *const p)
213 {
214 	struct audit_buffer *ab;
215 
216 	ab = audit_log_start(audit_context(), GFP_KERNEL,
217 			     AUDIT_IPE_POLICY_LOAD);
218 	if (!ab)
219 		return;
220 
221 	audit_policy(ab, AUDIT_POLICY_LOAD_FMT, p);
222 	audit_log_format(ab, " auid=%u ses=%u lsm=ipe res=1",
223 			 from_kuid(&init_user_ns, audit_get_loginuid(current)),
224 			 audit_get_sessionid(current));
225 
226 	audit_log_end(ab);
227 }
228 
229 /**
230  * ipe_audit_enforce() - Audit a change in IPE's enforcement state.
231  * @new_enforce: The new value enforce to be set.
232  * @old_enforce: The old value currently in enforce.
233  */
234 void ipe_audit_enforce(bool new_enforce, bool old_enforce)
235 {
236 	struct audit_buffer *ab;
237 
238 	ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_MAC_STATUS);
239 	if (!ab)
240 		return;
241 
242 	audit_log(audit_context(), GFP_KERNEL, AUDIT_MAC_STATUS,
243 		  "enforcing=%d old_enforcing=%d auid=%u ses=%u"
244 		  " enabled=1 old-enabled=1 lsm=ipe res=1",
245 		  new_enforce, old_enforce,
246 		  from_kuid(&init_user_ns, audit_get_loginuid(current)),
247 		  audit_get_sessionid(current));
248 
249 	audit_log_end(ab);
250 }
251