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
36static 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
47static const char *const audit_hook_names[__IPE_HOOK_MAX] = {
48 "BPRM_CHECK",
49 "MMAP",
50 "MPROTECT",
51 "KERNEL_READ",
52 "KERNEL_LOAD",
53};
54
55static 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 */
71static void audit_dmv_roothash(struct audit_buffer *ab, const void *rh)
72{
73 audit_log_format(ab, fmt: "%s", audit_prop_names[IPE_PROP_DMV_ROOTHASH]);
74 ipe_digest_audit(ab, val: 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 */
82static void audit_fsv_digest(struct audit_buffer *ab, const void *d)
83{
84 audit_log_format(ab, fmt: "%s", audit_prop_names[IPE_PROP_FSV_DIGEST]);
85 ipe_digest_audit(ab, val: 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 */
93static 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, fmt: " 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, rh: ptr->value);
103 break;
104 case IPE_PROP_FSV_DIGEST:
105 audit_fsv_digest(ab, d: ptr->value);
106 break;
107 default:
108 audit_log_format(ab, fmt: "%s", audit_prop_names[ptr->type]);
109 break;
110 }
111
112 audit_log_format(ab, fmt: " ");
113 }
114
115 audit_log_format(ab, fmt: "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 */
127void 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(ctx: audit_context(), GFP_ATOMIC | __GFP_NOWARN,
140 AUDIT_IPE_ACCESS);
141 if (!ab)
142 return;
143
144 audit_log_format(ab, fmt: "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, prefix: " path=", path: &ctx->file->f_path);
151 inode = file_inode(f: ctx->file);
152 if (inode) {
153 audit_log_format(ab, fmt: " dev=");
154 audit_log_untrustedstring(ab, string: inode->i_sb->s_id);
155 audit_log_format(ab, fmt: " ino=%lu", inode->i_ino);
156 } else {
157 audit_log_format(ab, fmt: " dev=? ino=?");
158 }
159 } else {
160 audit_log_format(ab, fmt: " 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, fmt: " rule=\"DEFAULT op=%s action=%s\"", op,
167 ACTSTR(act));
168 else
169 audit_log_format(ab, fmt: " 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 */
181static 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, type: 0, mask: 0);
190 if (IS_ERR(ptr: 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, data: p->pkcs7, len: p->pkcs7len))
203 goto out;
204
205 if (crypto_shash_final(desc, out: digest))
206 goto out;
207
208 audit_log_format(ab, fmt: 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, buf: digest, len: crypto_shash_digestsize(tfm));
212
213out:
214 kfree(objp: 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 */
223void 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(ctx: 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, p: op);
235 audit_log_format(ab, fmt: " ");
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, fmt: " ");
243 }
244 audit_policy(ab, AUDIT_NEW_ACTIVE_POLICY_FMT, p: np);
245 audit_log_format(ab, fmt: " auid=%u ses=%u lsm=ipe res=1",
246 from_kuid(to: &init_user_ns, uid: 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 */
256void 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(ctx: audit_context(), GFP_KERNEL,
262 AUDIT_IPE_POLICY_LOAD);
263 if (!ab)
264 return;
265
266 if (!IS_ERR(ptr: 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(ptr: p);
271 }
272
273 audit_log_format(ab, fmt: " auid=%u ses=%u lsm=ipe res=%d errno=%d",
274 from_kuid(to: &init_user_ns, uid: 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 */
285void ipe_audit_enforce(bool new_enforce, bool old_enforce)
286{
287 struct audit_buffer *ab;
288
289 ab = audit_log_start(ctx: audit_context(), GFP_KERNEL, AUDIT_MAC_STATUS);
290 if (!ab)
291 return;
292
293 audit_log(ctx: audit_context(), GFP_KERNEL, AUDIT_MAC_STATUS,
294 fmt: "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(to: &init_user_ns, uid: audit_get_loginuid(current)),
298 audit_get_sessionid(current));
299
300 audit_log_end(ab);
301}
302

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of linux/security/ipe/audit.c