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: Always return a file measurement in ima_file_hash()

__ima_inode_hash() checks if a digest has been already calculated by
looking for the integrity_iint_cache structure associated to the passed
inode.

Users of ima_file_hash() (e.g. eBPF) might be interested in obtaining the
information without having to setup an IMA policy so that the digest is
always available at the time they call this function.

In addition, they likely expect the digest to be fresh, e.g. recalculated
by IMA after a file write. Although getting the digest from the
bprm_committed_creds hook (as in the eBPF test) ensures that the digest is
fresh, as the IMA hook is executed before that hook, this is not always the
case (e.g. for the mmap_file hook).

Call ima_collect_measurement() in __ima_inode_hash(), if the file
descriptor is available (passed by ima_file_hash()) and the digest is not
available/not fresh, and store the file measurement in a temporary
integrity_iint_cache structure.

This change does not cause memory usage increase, due to using the
temporary integrity_iint_cache structure, and due to freeing the
ima_digest_data structure inside integrity_iint_cache before exiting from
__ima_inode_hash().

For compatibility reasons, the behavior of ima_inode_hash() remains
unchanged.

Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
Link: https://lore.kernel.org/bpf/20220302111404.193900-3-roberto.sassu@huawei.com

authored by

Roberto Sassu and committed by
Alexei Starovoitov
280fe836 bae60eef

+33 -13
+33 -13
security/integrity/ima/ima_main.c
··· 520 520 } 521 521 EXPORT_SYMBOL_GPL(ima_file_check); 522 522 523 - static int __ima_inode_hash(struct inode *inode, char *buf, size_t buf_size) 523 + static int __ima_inode_hash(struct inode *inode, struct file *file, char *buf, 524 + size_t buf_size) 524 525 { 525 - struct integrity_iint_cache *iint; 526 - int hash_algo; 526 + struct integrity_iint_cache *iint = NULL, tmp_iint; 527 + int rc, hash_algo; 527 528 528 - if (!ima_policy_flag) 529 - return -EOPNOTSUPP; 529 + if (ima_policy_flag) { 530 + iint = integrity_iint_find(inode); 531 + if (iint) 532 + mutex_lock(&iint->mutex); 533 + } 530 534 531 - iint = integrity_iint_find(inode); 535 + if ((!iint || !(iint->flags & IMA_COLLECTED)) && file) { 536 + if (iint) 537 + mutex_unlock(&iint->mutex); 538 + 539 + memset(&tmp_iint, 0, sizeof(tmp_iint)); 540 + tmp_iint.inode = inode; 541 + mutex_init(&tmp_iint.mutex); 542 + 543 + rc = ima_collect_measurement(&tmp_iint, file, NULL, 0, 544 + ima_hash_algo, NULL); 545 + if (rc < 0) 546 + return -EOPNOTSUPP; 547 + 548 + iint = &tmp_iint; 549 + mutex_lock(&iint->mutex); 550 + } 551 + 532 552 if (!iint) 533 553 return -EOPNOTSUPP; 534 - 535 - mutex_lock(&iint->mutex); 536 554 537 555 /* 538 556 * ima_file_hash can be called when ima_collect_measurement has still ··· 570 552 hash_algo = iint->ima_hash->algo; 571 553 mutex_unlock(&iint->mutex); 572 554 555 + if (iint == &tmp_iint) 556 + kfree(iint->ima_hash); 557 + 573 558 return hash_algo; 574 559 } 575 560 576 561 /** 577 - * ima_file_hash - return the stored measurement if a file has been hashed and 578 - * is in the iint cache. 562 + * ima_file_hash - return a measurement of the file 579 563 * @file: pointer to the file 580 564 * @buf: buffer in which to store the hash 581 565 * @buf_size: length of the buffer ··· 590 570 * The file hash returned is based on the entire file, including the appended 591 571 * signature. 592 572 * 593 - * If IMA is disabled or if no measurement is available, return -EOPNOTSUPP. 573 + * If the measurement cannot be performed, return -EOPNOTSUPP. 594 574 * If the parameters are incorrect, return -EINVAL. 595 575 */ 596 576 int ima_file_hash(struct file *file, char *buf, size_t buf_size) ··· 598 578 if (!file) 599 579 return -EINVAL; 600 580 601 - return __ima_inode_hash(file_inode(file), buf, buf_size); 581 + return __ima_inode_hash(file_inode(file), file, buf, buf_size); 602 582 } 603 583 EXPORT_SYMBOL_GPL(ima_file_hash); 604 584 ··· 625 605 if (!inode) 626 606 return -EINVAL; 627 607 628 - return __ima_inode_hash(inode, buf, buf_size); 608 + return __ima_inode_hash(inode, NULL, buf, buf_size); 629 609 } 630 610 EXPORT_SYMBOL_GPL(ima_inode_hash); 631 611