hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/security/integrity/ima/ima_api.c
....@@ -1,18 +1,13 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2008 IBM Corporation
34 *
45 * Author: Mimi Zohar <zohar@us.ibm.com>
56 *
6
- * This program is free software; you can redistribute it and/or
7
- * modify it under the terms of the GNU General Public License as
8
- * published by the Free Software Foundation, version 2 of the
9
- * License.
10
- *
117 * File: ima_api.c
128 * Implements must_appraise_or_measure, collect_measurement,
139 * appraise_measurement, store_measurement and store_template.
1410 */
15
-#include <linux/module.h>
1611 #include <linux/slab.h>
1712 #include <linux/file.h>
1813 #include <linux/fs.h>
....@@ -32,6 +27,7 @@
3227 for (i = 0; i < entry->template_desc->num_fields; i++)
3328 kfree(entry->template_data[i].data);
3429
30
+ kfree(entry->digests);
3531 kfree(entry);
3632 }
3733
....@@ -39,19 +35,36 @@
3935 * ima_alloc_init_template - create and initialize a new template entry
4036 */
4137 int ima_alloc_init_template(struct ima_event_data *event_data,
42
- struct ima_template_entry **entry)
38
+ struct ima_template_entry **entry,
39
+ struct ima_template_desc *desc)
4340 {
44
- struct ima_template_desc *template_desc = ima_template_desc_current();
41
+ struct ima_template_desc *template_desc;
42
+ struct tpm_digest *digests;
4543 int i, result = 0;
4644
47
- *entry = kzalloc(sizeof(**entry) + template_desc->num_fields *
48
- sizeof(struct ima_field_data), GFP_NOFS);
45
+ if (desc)
46
+ template_desc = desc;
47
+ else
48
+ template_desc = ima_template_desc_current();
49
+
50
+ *entry = kzalloc(struct_size(*entry, template_data,
51
+ template_desc->num_fields), GFP_NOFS);
4952 if (!*entry)
5053 return -ENOMEM;
5154
55
+ digests = kcalloc(NR_BANKS(ima_tpm_chip) + ima_extra_slots,
56
+ sizeof(*digests), GFP_NOFS);
57
+ if (!digests) {
58
+ kfree(*entry);
59
+ *entry = NULL;
60
+ return -ENOMEM;
61
+ }
62
+
63
+ (*entry)->digests = digests;
5264 (*entry)->template_desc = template_desc;
5365 for (i = 0; i < template_desc->num_fields; i++) {
54
- struct ima_template_field *field = template_desc->fields[i];
66
+ const struct ima_template_field *field =
67
+ template_desc->fields[i];
5568 u32 len;
5669
5770 result = field->field_init(event_data,
....@@ -94,26 +107,16 @@
94107 static const char audit_cause[] = "hashing_error";
95108 char *template_name = entry->template_desc->name;
96109 int result;
97
- struct {
98
- struct ima_digest_data hdr;
99
- char digest[TPM_DIGEST_SIZE];
100
- } hash;
101110
102111 if (!violation) {
103
- int num_fields = entry->template_desc->num_fields;
104
-
105
- /* this function uses default algo */
106
- hash.hdr.algo = HASH_ALGO_SHA1;
107112 result = ima_calc_field_array_hash(&entry->template_data[0],
108
- entry->template_desc,
109
- num_fields, &hash.hdr);
113
+ entry);
110114 if (result < 0) {
111115 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode,
112116 template_name, op,
113117 audit_cause, result, 0);
114118 return result;
115119 }
116
- memcpy(entry->digest, hash.hdr.digest, hash.hdr.length);
117120 }
118121 entry->pcr = pcr;
119122 result = ima_add_template_entry(entry, violation, op, inode, filename);
....@@ -133,15 +136,17 @@
133136 {
134137 struct ima_template_entry *entry;
135138 struct inode *inode = file_inode(file);
136
- struct ima_event_data event_data = {iint, file, filename, NULL, 0,
137
- cause};
139
+ struct ima_event_data event_data = { .iint = iint,
140
+ .file = file,
141
+ .filename = filename,
142
+ .violation = cause };
138143 int violation = 1;
139144 int result;
140145
141146 /* can overflow, only indicator */
142147 atomic_long_inc(&ima_htable.violations);
143148
144
- result = ima_alloc_init_template(&event_data, &entry);
149
+ result = ima_alloc_init_template(&event_data, &entry, NULL);
145150 if (result < 0) {
146151 result = -ENOMEM;
147152 goto err_out;
....@@ -157,18 +162,21 @@
157162
158163 /**
159164 * ima_get_action - appraise & measure decision based on policy.
160
- * @inode: pointer to inode to measure
165
+ * @inode: pointer to the inode associated with the object being validated
161166 * @cred: pointer to credentials structure to validate
162167 * @secid: secid of the task being validated
163168 * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXEC,
164169 * MAY_APPEND)
165170 * @func: caller identifier
166171 * @pcr: pointer filled in if matched measure policy sets pcr=
172
+ * @template_desc: pointer filled in if matched measure policy sets template=
173
+ * @keyring: keyring name used to determine the action
167174 *
168175 * The policy is defined in terms of keypairs:
169176 * subj=, obj=, type=, func=, mask=, fsmagic=
170177 * subj,obj, and type: are LSM specific.
171178 * func: FILE_CHECK | BPRM_CHECK | CREDS_CHECK | MMAP_CHECK | MODULE_CHECK
179
+ * | KEXEC_CMDLINE | KEY_CHECK
172180 * mask: contains the permission mask
173181 * fsmagic: hex value
174182 *
....@@ -176,13 +184,16 @@
176184 *
177185 */
178186 int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
179
- int mask, enum ima_hooks func, int *pcr)
187
+ int mask, enum ima_hooks func, int *pcr,
188
+ struct ima_template_desc **template_desc,
189
+ const char *keyring)
180190 {
181191 int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE | IMA_HASH;
182192
183193 flags &= ima_policy_flag;
184194
185
- return ima_match_policy(inode, cred, secid, func, mask, flags, pcr);
195
+ return ima_match_policy(inode, cred, secid, func, mask, flags, pcr,
196
+ template_desc, keyring);
186197 }
187198
188199 /*
....@@ -197,7 +208,7 @@
197208 */
198209 int ima_collect_measurement(struct integrity_iint_cache *iint,
199210 struct file *file, void *buf, loff_t size,
200
- enum hash_algo algo)
211
+ enum hash_algo algo, struct modsig *modsig)
201212 {
202213 const char *audit_cause = "failed";
203214 struct inode *inode = file_inode(file);
....@@ -210,6 +221,14 @@
210221 struct ima_digest_data hdr;
211222 char digest[IMA_MAX_DIGEST_SIZE];
212223 } hash;
224
+
225
+ /*
226
+ * Always collect the modsig, because IMA might have already collected
227
+ * the file digest without collecting the modsig in a previous
228
+ * measurement rule.
229
+ */
230
+ if (modsig)
231
+ ima_collect_modsig(modsig, buf, size);
213232
214233 if (iint->flags & IMA_COLLECTED)
215234 goto out;
....@@ -277,21 +296,32 @@
277296 void ima_store_measurement(struct integrity_iint_cache *iint,
278297 struct file *file, const unsigned char *filename,
279298 struct evm_ima_xattr_data *xattr_value,
280
- int xattr_len, int pcr)
299
+ int xattr_len, const struct modsig *modsig, int pcr,
300
+ struct ima_template_desc *template_desc)
281301 {
282302 static const char op[] = "add_template_measure";
283303 static const char audit_cause[] = "ENOMEM";
284304 int result = -ENOMEM;
285305 struct inode *inode = file_inode(file);
286306 struct ima_template_entry *entry;
287
- struct ima_event_data event_data = {iint, file, filename, xattr_value,
288
- xattr_len, NULL};
307
+ struct ima_event_data event_data = { .iint = iint,
308
+ .file = file,
309
+ .filename = filename,
310
+ .xattr_value = xattr_value,
311
+ .xattr_len = xattr_len,
312
+ .modsig = modsig };
289313 int violation = 0;
290314
291
- if (iint->measured_pcrs & (0x1 << pcr))
315
+ /*
316
+ * We still need to store the measurement in the case of MODSIG because
317
+ * we only have its contents to put in the list at the time of
318
+ * appraisal, but a file measurement from earlier might already exist in
319
+ * the measurement list.
320
+ */
321
+ if (iint->measured_pcrs & (0x1 << pcr) && !modsig)
292322 return;
293323
294
- result = ima_alloc_init_template(&event_data, &entry);
324
+ result = ima_alloc_init_template(&event_data, &entry, template_desc);
295325 if (result < 0) {
296326 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
297327 op, audit_cause, result, 0);
....@@ -335,7 +365,7 @@
335365 audit_log_untrustedstring(ab, filename);
336366 audit_log_format(ab, " hash=\"%s:%s\"", algo_name, hash);
337367
338
- audit_log_task_info(ab, current);
368
+ audit_log_task_info(ab);
339369 audit_log_end(ab);
340370
341371 iint->flags |= IMA_AUDITED;