Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ima: instantiate the bprm_creds_for_exec() hook

Like direct file execution (e.g. ./script.sh), indirect file execution
(e.g. sh script.sh) needs to be measured and appraised. Instantiate
the new security_bprm_creds_for_exec() hook to measure and verify the
indirect file's integrity. Unlike direct file execution, indirect file
execution is optionally enforced by the interpreter.

Differentiate kernel and userspace enforced integrity audit messages.

Co-developed-by: Roberto Sassu <roberto.sassu@huawei.com>
Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
Tested-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Mickaël Salaün <mic@digikod.net>
Signed-off-by: Mickaël Salaün <mic@digikod.net>
Link: https://lore.kernel.org/r/20241212174223.389435-9-mic@digikod.net
Signed-off-by: Kees Cook <kees@kernel.org>

authored by

Mimi Zohar and committed by
Kees Cook
95b3cdaf 2a69962b

+55 -2
+1
include/uapi/linux/audit.h
··· 161 161 #define AUDIT_INTEGRITY_RULE 1805 /* policy rule */ 162 162 #define AUDIT_INTEGRITY_EVM_XATTR 1806 /* New EVM-covered xattr */ 163 163 #define AUDIT_INTEGRITY_POLICY_RULE 1807 /* IMA policy rules */ 164 + #define AUDIT_INTEGRITY_USERSPACE 1808 /* Userspace enforced data integrity */ 164 165 165 166 #define AUDIT_KERNEL 2000 /* Asynchronous audit record. NOT A REQUEST. */ 166 167
+25 -2
security/integrity/ima/ima_appraise.c
··· 8 8 #include <linux/module.h> 9 9 #include <linux/init.h> 10 10 #include <linux/file.h> 11 + #include <linux/binfmts.h> 11 12 #include <linux/fs.h> 12 13 #include <linux/xattr.h> 13 14 #include <linux/magic.h> ··· 470 469 return rc; 471 470 } 472 471 472 + static bool is_bprm_creds_for_exec(enum ima_hooks func, struct file *file) 473 + { 474 + struct linux_binprm *bprm; 475 + 476 + if (func == BPRM_CHECK) { 477 + bprm = container_of(&file, struct linux_binprm, file); 478 + return bprm->is_check; 479 + } 480 + return false; 481 + } 482 + 473 483 /* 474 484 * ima_appraise_measurement - appraise file measurement 475 485 * ··· 495 483 int xattr_len, const struct modsig *modsig) 496 484 { 497 485 static const char op[] = "appraise_data"; 486 + int audit_msgno = AUDIT_INTEGRITY_DATA; 498 487 const char *cause = "unknown"; 499 488 struct dentry *dentry = file_dentry(file); 500 489 struct inode *inode = d_backing_inode(dentry); ··· 506 493 /* If not appraising a modsig, we need an xattr. */ 507 494 if (!(inode->i_opflags & IOP_XATTR) && !try_modsig) 508 495 return INTEGRITY_UNKNOWN; 496 + 497 + /* 498 + * Unlike any of the other LSM hooks where the kernel enforces file 499 + * integrity, enforcing file integrity for the bprm_creds_for_exec() 500 + * LSM hook with the AT_EXECVE_CHECK flag is left up to the discretion 501 + * of the script interpreter(userspace). Differentiate kernel and 502 + * userspace enforced integrity audit messages. 503 + */ 504 + if (is_bprm_creds_for_exec(func, file)) 505 + audit_msgno = AUDIT_INTEGRITY_USERSPACE; 509 506 510 507 /* If reading the xattr failed and there's no modsig, error out. */ 511 508 if (rc <= 0 && !try_modsig) { ··· 592 569 (iint->flags & IMA_FAIL_UNVERIFIABLE_SIGS))) { 593 570 status = INTEGRITY_FAIL; 594 571 cause = "unverifiable-signature"; 595 - integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename, 572 + integrity_audit_msg(audit_msgno, inode, filename, 596 573 op, cause, rc, 0); 597 574 } else if (status != INTEGRITY_PASS) { 598 575 /* Fix mode, but don't replace file signatures. */ ··· 612 589 status = INTEGRITY_PASS; 613 590 } 614 591 615 - integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename, 592 + integrity_audit_msg(audit_msgno, inode, filename, 616 593 op, cause, rc, 0); 617 594 } else { 618 595 ima_cache_flags(iint, func);
+29
security/integrity/ima/ima_main.c
··· 555 555 } 556 556 557 557 /** 558 + * ima_bprm_creds_for_exec - collect/store/appraise measurement. 559 + * @bprm: contains the linux_binprm structure 560 + * 561 + * Based on the IMA policy and the execveat(2) AT_EXECVE_CHECK flag, measure 562 + * and appraise the integrity of a file to be executed by script interpreters. 563 + * Unlike any of the other LSM hooks where the kernel enforces file integrity, 564 + * enforcing file integrity is left up to the discretion of the script 565 + * interpreter (userspace). 566 + * 567 + * On success return 0. On integrity appraisal error, assuming the file 568 + * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. 569 + */ 570 + static int ima_bprm_creds_for_exec(struct linux_binprm *bprm) 571 + { 572 + /* 573 + * As security_bprm_check() is called multiple times, both 574 + * the script and the shebang interpreter are measured, appraised, 575 + * and audited. Limit usage of this LSM hook to just measuring, 576 + * appraising, and auditing the indirect script execution 577 + * (e.g. ./sh example.sh). 578 + */ 579 + if (!bprm->is_check) 580 + return 0; 581 + 582 + return ima_bprm_check(bprm); 583 + } 584 + 585 + /** 558 586 * ima_file_check - based on policy, collect/store measurement. 559 587 * @file: pointer to the file to be measured 560 588 * @mask: contains MAY_READ, MAY_WRITE, MAY_EXEC or MAY_APPEND ··· 1202 1174 1203 1175 static struct security_hook_list ima_hooks[] __ro_after_init = { 1204 1176 LSM_HOOK_INIT(bprm_check_security, ima_bprm_check), 1177 + LSM_HOOK_INIT(bprm_creds_for_exec, ima_bprm_creds_for_exec), 1205 1178 LSM_HOOK_INIT(file_post_open, ima_file_check), 1206 1179 LSM_HOOK_INIT(inode_post_create_tmpfile, ima_post_create_tmpfile), 1207 1180 LSM_HOOK_INIT(file_release, ima_file_free),