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