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: 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: 95b3cdafd7cb7 ("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>

authored by

Chris J Arges and committed by
Mimi Zohar
377cae98 f8f9c1f4

+20 -24
+4 -2
security/integrity/ima/ima.h
··· 441 441 int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint, 442 442 struct file *file, const unsigned char *filename, 443 443 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); 445 446 int ima_must_appraise(struct mnt_idmap *idmap, struct inode *inode, 446 447 int mask, enum ima_hooks func); 447 448 void ima_update_xattr(struct ima_iint_cache *iint, struct file *file); ··· 467 466 const unsigned char *filename, 468 467 struct evm_ima_xattr_data *xattr_value, 469 468 int xattr_len, 470 - const struct modsig *modsig) 469 + const struct modsig *modsig, 470 + bool bprm_is_check) 471 471 { 472 472 return INTEGRITY_UNKNOWN; 473 473 }
+3 -13
security/integrity/ima/ima_appraise.c
··· 470 470 return rc; 471 471 } 472 472 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 - 484 473 /* 485 474 * ima_appraise_measurement - appraise file measurement 486 475 * ··· 481 492 int ima_appraise_measurement(enum ima_hooks func, struct ima_iint_cache *iint, 482 493 struct file *file, const unsigned char *filename, 483 494 struct evm_ima_xattr_data *xattr_value, 484 - int xattr_len, const struct modsig *modsig) 495 + int xattr_len, const struct modsig *modsig, 496 + bool bprm_is_check) 485 497 { 486 498 static const char op[] = "appraise_data"; 487 499 int audit_msgno = AUDIT_INTEGRITY_DATA; ··· 504 514 * of the script interpreter(userspace). Differentiate kernel and 505 515 * userspace enforced integrity audit messages. 506 516 */ 507 - if (is_bprm_creds_for_exec(func, file)) 517 + if (bprm_is_check) 508 518 audit_msgno = AUDIT_INTEGRITY_USERSPACE; 509 519 510 520 /* If reading the xattr failed and there's no modsig, error out. */
+13 -9
security/integrity/ima/ima_main.c
··· 236 236 static int process_measurement(struct file *file, const struct cred *cred, 237 237 struct lsm_prop *prop, char *buf, loff_t size, 238 238 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) 240 241 { 241 242 struct inode *real_inode, *inode = file_inode(file); 242 243 struct ima_iint_cache *iint = NULL; ··· 427 426 inode_lock(inode); 428 427 rc = ima_appraise_measurement(func, iint, file, 429 428 pathname, xattr_value, 430 - xattr_len, modsig); 429 + xattr_len, modsig, 430 + bprm_is_check); 431 431 inode_unlock(inode); 432 432 } 433 433 if (!rc) ··· 495 493 496 494 if (reqprot & PROT_EXEC) { 497 495 ret = process_measurement(file, current_cred(), &prop, NULL, 498 - 0, MAY_EXEC, MMAP_CHECK_REQPROT, 0); 496 + 0, MAY_EXEC, MMAP_CHECK_REQPROT, 0, 497 + false); 499 498 if (ret) 500 499 return ret; 501 500 } 502 501 503 502 if (prot & PROT_EXEC) 504 503 return process_measurement(file, current_cred(), &prop, NULL, 505 - 0, MAY_EXEC, MMAP_CHECK, 0); 504 + 0, MAY_EXEC, MMAP_CHECK, 0, false); 506 505 507 506 return 0; 508 507 } ··· 587 584 588 585 security_current_getlsmprop_subj(&prop); 589 586 return process_measurement(bprm->file, current_cred(), 590 - &prop, NULL, 0, MAY_EXEC, BPRM_CHECK, 0); 587 + &prop, NULL, 0, MAY_EXEC, BPRM_CHECK, 0, 588 + bprm->is_check); 591 589 } 592 590 593 591 /** ··· 618 614 619 615 security_current_getlsmprop_subj(&prop); 620 616 return process_measurement((struct file *)file, bprm->cred, &prop, NULL, 621 - 0, MAY_EXEC, CREDS_CHECK, 0); 617 + 0, MAY_EXEC, CREDS_CHECK, 0, false); 622 618 } 623 619 624 620 /** ··· 666 662 security_current_getlsmprop_subj(&prop); 667 663 return process_measurement(file, current_cred(), &prop, NULL, 0, 668 664 mask & (MAY_READ | MAY_WRITE | MAY_EXEC | 669 - MAY_APPEND), FILE_CHECK, 0); 665 + MAY_APPEND), FILE_CHECK, 0, false); 670 666 } 671 667 672 668 static int __ima_inode_hash(struct inode *inode, struct file *file, char *buf, ··· 885 881 func = read_idmap[read_id] ?: FILE_CHECK; 886 882 security_current_getlsmprop_subj(&prop); 887 883 return process_measurement(file, current_cred(), &prop, NULL, 0, 888 - MAY_READ, func, 0); 884 + MAY_READ, func, 0, false); 889 885 } 890 886 891 887 const int read_idmap[READING_MAX_ID] = { ··· 929 925 func = read_idmap[read_id] ?: FILE_CHECK; 930 926 security_current_getlsmprop_subj(&prop); 931 927 return process_measurement(file, current_cred(), &prop, buf, size, 932 - MAY_READ, func, read_id); 928 + MAY_READ, func, read_id, false); 933 929 } 934 930 935 931 /**