Skip to content

Commit 377cae9

Browse files
argesmimizohar
authored andcommitted
ima: Fix stack-out-of-bounds in is_bprm_creds_for_exec()
KASAN reported a stack-out-of-bounds access in ima_appraise_measurement from is_bprm_creds_for_exec: BUG: KASAN: stack-out-of-bounds in ima_appraise_measurement+0x12dc/0x16a0 Read of size 1 at addr ffffc9000160f940 by task sudo/550 The buggy address belongs to stack of task sudo/550 and is located at offset 24 in frame: ima_appraise_measurement+0x0/0x16a0 This frame has 2 objects: [48, 56) 'file' [80, 148) 'hash' This is caused by using container_of on the *file pointer. This offset calculation is what triggers the stack-out-of-bounds error. In order to fix this, pass in a bprm_is_check boolean which can be set depending on how process_measurement is called. If the caller has a linux_binprm pointer and the function is BPRM_CHECK we can determine is_check and set it then. Otherwise set it to false. Fixes: 95b3cda ("ima: instantiate the bprm_creds_for_exec() hook") Signed-off-by: Chris J Arges <carges@cloudflare.com> Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
1 parent f8f9c1f commit 377cae9

3 files changed

Lines changed: 20 additions & 24 deletions

File tree

security/integrity/ima/ima.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,8 @@ int ima_check_blacklist(struct ima_iint_cache *iint,
441441
int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint,
442442
struct file *file, const unsigned char *filename,
443443
struct evm_ima_xattr_data *xattr_value,
444-
int xattr_len, const struct modsig *modsig);
444+
int xattr_len, const struct modsig *modsig,
445+
bool bprm_is_check);
445446
int ima_must_appraise(struct mnt_idmap *idmap, struct inode *inode,
446447
int mask, enum ima_hooks func);
447448
void ima_update_xattr(struct ima_iint_cache *iint, struct file *file);
@@ -466,7 +467,8 @@ static inline int ima_appraise_measurement(enum ima_hooks func,
466467
const unsigned char *filename,
467468
struct evm_ima_xattr_data *xattr_value,
468469
int xattr_len,
469-
const struct modsig *modsig)
470+
const struct modsig *modsig,
471+
bool bprm_is_check)
470472
{
471473
return INTEGRITY_UNKNOWN;
472474
}

security/integrity/ima/ima_appraise.c

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -470,17 +470,6 @@ int ima_check_blacklist(struct ima_iint_cache *iint,
470470
return rc;
471471
}
472472

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-
484473
/*
485474
* ima_appraise_measurement - appraise file measurement
486475
*
@@ -492,7 +481,8 @@ static bool is_bprm_creds_for_exec(enum ima_hooks func, struct file *file)
492481
int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint,
493482
struct file *file, const unsigned char *filename,
494483
struct evm_ima_xattr_data *xattr_value,
495-
int xattr_len, const struct modsig *modsig)
484+
int xattr_len, const struct modsig *modsig,
485+
bool bprm_is_check)
496486
{
497487
static const char op[] = "appraise_data";
498488
int audit_msgno = AUDIT_INTEGRITY_DATA;
@@ -514,7 +504,7 @@ int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint,
514504
* of the script interpreter(userspace). Differentiate kernel and
515505
* userspace enforced integrity audit messages.
516506
*/
517-
if (is_bprm_creds_for_exec(func, file))
507+
if (bprm_is_check)
518508
audit_msgno = AUDIT_INTEGRITY_USERSPACE;
519509

520510
/* If reading the xattr failed and there's no modsig, error out. */

security/integrity/ima/ima_main.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,8 @@ static void ima_file_free(struct file *file)
236236
static int process_measurement(struct file *file, const struct cred *cred,
237237
struct lsm_prop *prop, char *buf, loff_t size,
238238
int mask, enum ima_hooks func,
239-
enum kernel_read_file_id read_id)
239+
enum kernel_read_file_id read_id,
240+
bool bprm_is_check)
240241
{
241242
struct inode *real_inode, *inode = file_inode(file);
242243
struct ima_iint_cache *iint = NULL;
@@ -426,7 +427,8 @@ static int process_measurement(struct file *file, const struct cred *cred,
426427
inode_lock(inode);
427428
rc = ima_appraise_measurement(func, iint, file,
428429
pathname, xattr_value,
429-
xattr_len, modsig);
430+
xattr_len, modsig,
431+
bprm_is_check);
430432
inode_unlock(inode);
431433
}
432434
if (!rc)
@@ -493,14 +495,15 @@ static int ima_file_mmap(struct file *file, unsigned long reqprot,
493495

494496
if (reqprot & PROT_EXEC) {
495497
ret = process_measurement(file, current_cred(), &prop, NULL,
496-
0, MAY_EXEC, MMAP_CHECK_REQPROT, 0);
498+
0, MAY_EXEC, MMAP_CHECK_REQPROT, 0,
499+
false);
497500
if (ret)
498501
return ret;
499502
}
500503

501504
if (prot & PROT_EXEC)
502505
return process_measurement(file, current_cred(), &prop, NULL,
503-
0, MAY_EXEC, MMAP_CHECK, 0);
506+
0, MAY_EXEC, MMAP_CHECK, 0, false);
504507

505508
return 0;
506509
}
@@ -584,7 +587,8 @@ static int ima_bprm_check(struct linux_binprm *bprm)
584587

585588
security_current_getlsmprop_subj(&prop);
586589
return process_measurement(bprm->file, current_cred(),
587-
&prop, NULL, 0, MAY_EXEC, BPRM_CHECK, 0);
590+
&prop, NULL, 0, MAY_EXEC, BPRM_CHECK, 0,
591+
bprm->is_check);
588592
}
589593

590594
/**
@@ -614,7 +618,7 @@ static int ima_creds_check(struct linux_binprm *bprm, const struct file *file)
614618

615619
security_current_getlsmprop_subj(&prop);
616620
return process_measurement((struct file *)file, bprm->cred, &prop, NULL,
617-
0, MAY_EXEC, CREDS_CHECK, 0);
621+
0, MAY_EXEC, CREDS_CHECK, 0, false);
618622
}
619623

620624
/**
@@ -662,7 +666,7 @@ static int ima_file_check(struct file *file, int mask)
662666
security_current_getlsmprop_subj(&prop);
663667
return process_measurement(file, current_cred(), &prop, NULL, 0,
664668
mask & (MAY_READ | MAY_WRITE | MAY_EXEC |
665-
MAY_APPEND), FILE_CHECK, 0);
669+
MAY_APPEND), FILE_CHECK, 0, false);
666670
}
667671

668672
static int __ima_inode_hash(struct inode *inode, struct file *file, char *buf,
@@ -881,7 +885,7 @@ static int ima_read_file(struct file *file, enum kernel_read_file_id read_id,
881885
func = read_idmap[read_id] ?: FILE_CHECK;
882886
security_current_getlsmprop_subj(&prop);
883887
return process_measurement(file, current_cred(), &prop, NULL, 0,
884-
MAY_READ, func, 0);
888+
MAY_READ, func, 0, false);
885889
}
886890

887891
const int read_idmap[READING_MAX_ID] = {
@@ -925,7 +929,7 @@ static int ima_post_read_file(struct file *file, char *buf, loff_t size,
925929
func = read_idmap[read_id] ?: FILE_CHECK;
926930
security_current_getlsmprop_subj(&prop);
927931
return process_measurement(file, current_cred(), &prop, buf, size,
928-
MAY_READ, func, read_id);
932+
MAY_READ, func, read_id, false);
929933
}
930934

931935
/**

0 commit comments

Comments
 (0)