Skip to content

Commit 95b3cda

Browse files
mimizoharkees
authored andcommitted
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>
1 parent 2a69962 commit 95b3cda

File tree

3 files changed

+55
-2
lines changed

3 files changed

+55
-2
lines changed

include/uapi/linux/audit.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@
161161
#define AUDIT_INTEGRITY_RULE 1805 /* policy rule */
162162
#define AUDIT_INTEGRITY_EVM_XATTR 1806 /* New EVM-covered xattr */
163163
#define AUDIT_INTEGRITY_POLICY_RULE 1807 /* IMA policy rules */
164+
#define AUDIT_INTEGRITY_USERSPACE 1808 /* Userspace enforced data integrity */
164165

165166
#define AUDIT_KERNEL 2000 /* Asynchronous audit record. NOT A REQUEST. */
166167

security/integrity/ima/ima_appraise.c

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/module.h>
99
#include <linux/init.h>
1010
#include <linux/file.h>
11+
#include <linux/binfmts.h>
1112
#include <linux/fs.h>
1213
#include <linux/xattr.h>
1314
#include <linux/magic.h>
@@ -469,6 +470,17 @@ int ima_check_blacklist(struct ima_iint_cache *iint,
469470
return rc;
470471
}
471472

473+
static bool is_bprm_creds_for_exec(enum ima_hooks func, struct file *file)
474+
{
475+
struct linux_binprm *bprm;
476+
477+
if (func == BPRM_CHECK) {
478+
bprm = container_of(&file, struct linux_binprm, file);
479+
return bprm->is_check;
480+
}
481+
return false;
482+
}
483+
472484
/*
473485
* ima_appraise_measurement - appraise file measurement
474486
*
@@ -483,6 +495,7 @@ int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint,
483495
int xattr_len, const struct modsig *modsig)
484496
{
485497
static const char op[] = "appraise_data";
498+
int audit_msgno = AUDIT_INTEGRITY_DATA;
486499
const char *cause = "unknown";
487500
struct dentry *dentry = file_dentry(file);
488501
struct inode *inode = d_backing_inode(dentry);
@@ -494,6 +507,16 @@ int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint,
494507
if (!(inode->i_opflags & IOP_XATTR) && !try_modsig)
495508
return INTEGRITY_UNKNOWN;
496509

510+
/*
511+
* Unlike any of the other LSM hooks where the kernel enforces file
512+
* integrity, enforcing file integrity for the bprm_creds_for_exec()
513+
* LSM hook with the AT_EXECVE_CHECK flag is left up to the discretion
514+
* of the script interpreter(userspace). Differentiate kernel and
515+
* userspace enforced integrity audit messages.
516+
*/
517+
if (is_bprm_creds_for_exec(func, file))
518+
audit_msgno = AUDIT_INTEGRITY_USERSPACE;
519+
497520
/* If reading the xattr failed and there's no modsig, error out. */
498521
if (rc <= 0 && !try_modsig) {
499522
if (rc && rc != -ENODATA)
@@ -569,7 +592,7 @@ int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint,
569592
(iint->flags & IMA_FAIL_UNVERIFIABLE_SIGS))) {
570593
status = INTEGRITY_FAIL;
571594
cause = "unverifiable-signature";
572-
integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
595+
integrity_audit_msg(audit_msgno, inode, filename,
573596
op, cause, rc, 0);
574597
} else if (status != INTEGRITY_PASS) {
575598
/* Fix mode, but don't replace file signatures. */
@@ -589,7 +612,7 @@ int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint,
589612
status = INTEGRITY_PASS;
590613
}
591614

592-
integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
615+
integrity_audit_msg(audit_msgno, inode, filename,
593616
op, cause, rc, 0);
594617
} else {
595618
ima_cache_flags(iint, func);

security/integrity/ima/ima_main.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,34 @@ static int ima_bprm_check(struct linux_binprm *bprm)
554554
MAY_EXEC, CREDS_CHECK);
555555
}
556556

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+
557585
/**
558586
* ima_file_check - based on policy, collect/store measurement.
559587
* @file: pointer to the file to be measured
@@ -1174,6 +1202,7 @@ static int __init init_ima(void)
11741202

11751203
static struct security_hook_list ima_hooks[] __ro_after_init = {
11761204
LSM_HOOK_INIT(bprm_check_security, ima_bprm_check),
1205+
LSM_HOOK_INIT(bprm_creds_for_exec, ima_bprm_creds_for_exec),
11771206
LSM_HOOK_INIT(file_post_open, ima_file_check),
11781207
LSM_HOOK_INIT(inode_post_create_tmpfile, ima_post_create_tmpfile),
11791208
LSM_HOOK_INIT(file_release, ima_file_free),

0 commit comments

Comments
 (0)