forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 23fa18eaa71266feff7ba8d83022d9e1cc83c65a
kernel/security/integrity/ima/ima_appraise.c
....@@ -1,32 +1,47 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2011 IBM Corporation
34 *
45 * Author:
56 * Mimi Zohar <zohar@us.ibm.com>
6
- *
7
- * This program is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License as published by
9
- * the Free Software Foundation, version 2 of the License.
107 */
11
-#include <linux/module.h>
8
+#include <linux/init.h>
129 #include <linux/file.h>
1310 #include <linux/fs.h>
1411 #include <linux/xattr.h>
1512 #include <linux/magic.h>
1613 #include <linux/ima.h>
1714 #include <linux/evm.h>
15
+#include <keys/system_keyring.h>
1816
1917 #include "ima.h"
2018
2119 static int __init default_appraise_setup(char *str)
2220 {
2321 #ifdef CONFIG_IMA_APPRAISE_BOOTPARAM
22
+ bool sb_state = arch_ima_get_secureboot();
23
+ int appraisal_state = ima_appraise;
24
+
2425 if (strncmp(str, "off", 3) == 0)
25
- ima_appraise = 0;
26
+ appraisal_state = 0;
2627 else if (strncmp(str, "log", 3) == 0)
27
- ima_appraise = IMA_APPRAISE_LOG;
28
+ appraisal_state = IMA_APPRAISE_LOG;
2829 else if (strncmp(str, "fix", 3) == 0)
29
- ima_appraise = IMA_APPRAISE_FIX;
30
+ appraisal_state = IMA_APPRAISE_FIX;
31
+ else if (strncmp(str, "enforce", 7) == 0)
32
+ appraisal_state = IMA_APPRAISE_ENFORCE;
33
+ else
34
+ pr_err("invalid \"%s\" appraise option", str);
35
+
36
+ /* If appraisal state was changed, but secure boot is enabled,
37
+ * keep its default */
38
+ if (sb_state) {
39
+ if (!(appraisal_state & IMA_APPRAISE_ENFORCE))
40
+ pr_info("Secure boot enabled: ignoring ima_appraise=%s option",
41
+ str);
42
+ } else {
43
+ ima_appraise = appraisal_state;
44
+ }
3045 #endif
3146 return 1;
3247 }
....@@ -57,7 +72,7 @@
5772
5873 security_task_getsecid(current, &secid);
5974 return ima_match_policy(inode, current_cred(), secid, func, mask,
60
- IMA_APPRAISE | IMA_HASH, NULL);
75
+ IMA_APPRAISE | IMA_HASH, NULL, NULL, NULL);
6176 }
6277
6378 static int ima_fix_xattr(struct dentry *dentry,
....@@ -114,6 +129,7 @@
114129 break;
115130 case CREDS_CHECK:
116131 iint->ima_creds_status = status;
132
+ break;
117133 case FILE_CHECK:
118134 case POST_SETATTR:
119135 iint->ima_file_status = status;
....@@ -167,7 +183,8 @@
167183 return sig->hash_algo;
168184 break;
169185 case IMA_XATTR_DIGEST_NG:
170
- ret = xattr_value->digest[0];
186
+ /* first byte contains algorithm id */
187
+ ret = xattr_value->data[0];
171188 if (ret < HASH_ALGO__LAST)
172189 return ret;
173190 break;
....@@ -175,7 +192,7 @@
175192 /* this is for backward compatibility */
176193 if (xattr_len == 21) {
177194 unsigned int zero = 0;
178
- if (!memcmp(&xattr_value->digest[16], &zero, 4))
195
+ if (!memcmp(&xattr_value->data[16], &zero, 4))
179196 return HASH_ALGO_MD5;
180197 else
181198 return HASH_ALGO_SHA1;
....@@ -201,6 +218,142 @@
201218 }
202219
203220 /*
221
+ * xattr_verify - verify xattr digest or signature
222
+ *
223
+ * Verify whether the hash or signature matches the file contents.
224
+ *
225
+ * Return 0 on success, error code otherwise.
226
+ */
227
+static int xattr_verify(enum ima_hooks func, struct integrity_iint_cache *iint,
228
+ struct evm_ima_xattr_data *xattr_value, int xattr_len,
229
+ enum integrity_status *status, const char **cause)
230
+{
231
+ int rc = -EINVAL, hash_start = 0;
232
+
233
+ switch (xattr_value->type) {
234
+ case IMA_XATTR_DIGEST_NG:
235
+ /* first byte contains algorithm id */
236
+ hash_start = 1;
237
+ fallthrough;
238
+ case IMA_XATTR_DIGEST:
239
+ if (iint->flags & IMA_DIGSIG_REQUIRED) {
240
+ *cause = "IMA-signature-required";
241
+ *status = INTEGRITY_FAIL;
242
+ break;
243
+ }
244
+ clear_bit(IMA_DIGSIG, &iint->atomic_flags);
245
+ if (xattr_len - sizeof(xattr_value->type) - hash_start >=
246
+ iint->ima_hash->length)
247
+ /*
248
+ * xattr length may be longer. md5 hash in previous
249
+ * version occupied 20 bytes in xattr, instead of 16
250
+ */
251
+ rc = memcmp(&xattr_value->data[hash_start],
252
+ iint->ima_hash->digest,
253
+ iint->ima_hash->length);
254
+ else
255
+ rc = -EINVAL;
256
+ if (rc) {
257
+ *cause = "invalid-hash";
258
+ *status = INTEGRITY_FAIL;
259
+ break;
260
+ }
261
+ *status = INTEGRITY_PASS;
262
+ break;
263
+ case EVM_IMA_XATTR_DIGSIG:
264
+ set_bit(IMA_DIGSIG, &iint->atomic_flags);
265
+ rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
266
+ (const char *)xattr_value,
267
+ xattr_len,
268
+ iint->ima_hash->digest,
269
+ iint->ima_hash->length);
270
+ if (rc == -EOPNOTSUPP) {
271
+ *status = INTEGRITY_UNKNOWN;
272
+ break;
273
+ }
274
+ if (IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING) && rc &&
275
+ func == KEXEC_KERNEL_CHECK)
276
+ rc = integrity_digsig_verify(INTEGRITY_KEYRING_PLATFORM,
277
+ (const char *)xattr_value,
278
+ xattr_len,
279
+ iint->ima_hash->digest,
280
+ iint->ima_hash->length);
281
+ if (rc) {
282
+ *cause = "invalid-signature";
283
+ *status = INTEGRITY_FAIL;
284
+ } else {
285
+ *status = INTEGRITY_PASS;
286
+ }
287
+ break;
288
+ default:
289
+ *status = INTEGRITY_UNKNOWN;
290
+ *cause = "unknown-ima-data";
291
+ break;
292
+ }
293
+
294
+ return rc;
295
+}
296
+
297
+/*
298
+ * modsig_verify - verify modsig signature
299
+ *
300
+ * Verify whether the signature matches the file contents.
301
+ *
302
+ * Return 0 on success, error code otherwise.
303
+ */
304
+static int modsig_verify(enum ima_hooks func, const struct modsig *modsig,
305
+ enum integrity_status *status, const char **cause)
306
+{
307
+ int rc;
308
+
309
+ rc = integrity_modsig_verify(INTEGRITY_KEYRING_IMA, modsig);
310
+ if (IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING) && rc &&
311
+ func == KEXEC_KERNEL_CHECK)
312
+ rc = integrity_modsig_verify(INTEGRITY_KEYRING_PLATFORM,
313
+ modsig);
314
+ if (rc) {
315
+ *cause = "invalid-signature";
316
+ *status = INTEGRITY_FAIL;
317
+ } else {
318
+ *status = INTEGRITY_PASS;
319
+ }
320
+
321
+ return rc;
322
+}
323
+
324
+/*
325
+ * ima_check_blacklist - determine if the binary is blacklisted.
326
+ *
327
+ * Add the hash of the blacklisted binary to the measurement list, based
328
+ * on policy.
329
+ *
330
+ * Returns -EPERM if the hash is blacklisted.
331
+ */
332
+int ima_check_blacklist(struct integrity_iint_cache *iint,
333
+ const struct modsig *modsig, int pcr)
334
+{
335
+ enum hash_algo hash_algo;
336
+ const u8 *digest = NULL;
337
+ u32 digestsize = 0;
338
+ int rc = 0;
339
+
340
+ if (!(iint->flags & IMA_CHECK_BLACKLIST))
341
+ return 0;
342
+
343
+ if (iint->flags & IMA_MODSIG_ALLOWED && modsig) {
344
+ ima_get_modsig_digest(modsig, &hash_algo, &digest, &digestsize);
345
+
346
+ rc = is_binary_blacklisted(digest, digestsize);
347
+ if ((rc == -EPERM) && (iint->flags & IMA_MEASURE))
348
+ process_buffer_measurement(NULL, digest, digestsize,
349
+ "blacklisted-hash", NONE,
350
+ pcr, NULL);
351
+ }
352
+
353
+ return rc;
354
+}
355
+
356
+/*
204357 * ima_appraise_measurement - appraise file measurement
205358 *
206359 * Call evm_verifyxattr() to verify the integrity of 'security.ima'.
....@@ -212,19 +365,22 @@
212365 struct integrity_iint_cache *iint,
213366 struct file *file, const unsigned char *filename,
214367 struct evm_ima_xattr_data *xattr_value,
215
- int xattr_len)
368
+ int xattr_len, const struct modsig *modsig)
216369 {
217370 static const char op[] = "appraise_data";
218371 const char *cause = "unknown";
219372 struct dentry *dentry = file_dentry(file);
220373 struct inode *inode = d_backing_inode(dentry);
221374 enum integrity_status status = INTEGRITY_UNKNOWN;
222
- int rc = xattr_len, hash_start = 0;
375
+ int rc = xattr_len;
376
+ bool try_modsig = iint->flags & IMA_MODSIG_ALLOWED && modsig;
223377
224
- if (!(inode->i_opflags & IOP_XATTR))
378
+ /* If not appraising a modsig, we need an xattr. */
379
+ if (!(inode->i_opflags & IOP_XATTR) && !try_modsig)
225380 return INTEGRITY_UNKNOWN;
226381
227
- if (rc <= 0) {
382
+ /* If reading the xattr failed and there's no modsig, error out. */
383
+ if (rc <= 0 && !try_modsig) {
228384 if (rc && rc != -ENODATA)
229385 goto out;
230386
....@@ -240,13 +396,18 @@
240396 goto out;
241397 }
242398
243
- status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
399
+ status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value,
400
+ rc < 0 ? 0 : rc, iint);
244401 switch (status) {
245402 case INTEGRITY_PASS:
246403 case INTEGRITY_PASS_IMMUTABLE:
247404 case INTEGRITY_UNKNOWN:
248405 break;
249406 case INTEGRITY_NOXATTRS: /* No EVM protected xattrs. */
407
+ /* It's fine not to have xattrs when using a modsig. */
408
+ if (try_modsig)
409
+ break;
410
+ fallthrough;
250411 case INTEGRITY_NOLABEL: /* No security.evm xattr. */
251412 cause = "missing-HMAC";
252413 goto out;
....@@ -257,55 +418,18 @@
257418 WARN_ONCE(true, "Unexpected integrity status %d\n", status);
258419 }
259420
260
- switch (xattr_value->type) {
261
- case IMA_XATTR_DIGEST_NG:
262
- /* first byte contains algorithm id */
263
- hash_start = 1;
264
- /* fall through */
265
- case IMA_XATTR_DIGEST:
266
- if (iint->flags & IMA_DIGSIG_REQUIRED) {
267
- cause = "IMA-signature-required";
268
- status = INTEGRITY_FAIL;
269
- break;
270
- }
271
- clear_bit(IMA_DIGSIG, &iint->atomic_flags);
272
- if (xattr_len - sizeof(xattr_value->type) - hash_start >=
273
- iint->ima_hash->length)
274
- /* xattr length may be longer. md5 hash in previous
275
- version occupied 20 bytes in xattr, instead of 16
276
- */
277
- rc = memcmp(&xattr_value->digest[hash_start],
278
- iint->ima_hash->digest,
279
- iint->ima_hash->length);
280
- else
281
- rc = -EINVAL;
282
- if (rc) {
283
- cause = "invalid-hash";
284
- status = INTEGRITY_FAIL;
285
- break;
286
- }
287
- status = INTEGRITY_PASS;
288
- break;
289
- case EVM_IMA_XATTR_DIGSIG:
290
- set_bit(IMA_DIGSIG, &iint->atomic_flags);
291
- rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
292
- (const char *)xattr_value, rc,
293
- iint->ima_hash->digest,
294
- iint->ima_hash->length);
295
- if (rc == -EOPNOTSUPP) {
296
- status = INTEGRITY_UNKNOWN;
297
- } else if (rc) {
298
- cause = "invalid-signature";
299
- status = INTEGRITY_FAIL;
300
- } else {
301
- status = INTEGRITY_PASS;
302
- }
303
- break;
304
- default:
305
- status = INTEGRITY_UNKNOWN;
306
- cause = "unknown-ima-data";
307
- break;
308
- }
421
+ if (xattr_value)
422
+ rc = xattr_verify(func, iint, xattr_value, xattr_len, &status,
423
+ &cause);
424
+
425
+ /*
426
+ * If we have a modsig and either no imasig or the imasig's key isn't
427
+ * known, then try verifying the modsig.
428
+ */
429
+ if (try_modsig &&
430
+ (!xattr_value || xattr_value->type == IMA_XATTR_DIGEST_NG ||
431
+ rc == -ENOKEY))
432
+ rc = modsig_verify(func, modsig, &status, &cause);
309433
310434 out:
311435 /*
....@@ -323,7 +447,7 @@
323447 op, cause, rc, 0);
324448 } else if (status != INTEGRITY_PASS) {
325449 /* Fix mode, but don't replace file signatures. */
326
- if ((ima_appraise & IMA_APPRAISE_FIX) &&
450
+ if ((ima_appraise & IMA_APPRAISE_FIX) && !try_modsig &&
327451 (!xattr_value ||
328452 xattr_value->type != EVM_IMA_XATTR_DIGSIG)) {
329453 if (!ima_fix_xattr(dentry, iint))
....@@ -362,7 +486,7 @@
362486 !(iint->flags & IMA_HASH))
363487 return;
364488
365
- rc = ima_collect_measurement(iint, file, NULL, 0, ima_hash_algo);
489
+ rc = ima_collect_measurement(iint, file, NULL, 0, ima_hash_algo, NULL);
366490 if (rc < 0)
367491 return;
368492