From d79d72e02485c00b886179538dc8deaffa3be507 Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Mon, 3 Dec 2012 17:08:11 -0500 Subject: ima: per hook cache integrity appraisal status With the new IMA policy 'appraise_type=' option, different hooks can require different methods for appraising a file's integrity. For example, the existing 'ima_appraise_tcb' policy defines a generic rule, requiring all root files to be appraised, without specfying the appraisal method. A more specific rule could require all kernel modules, for example, to be signed. appraise fowner=0 func=MODULE_CHECK appraise_type=imasig appraise fowner=0 As a result, the integrity appraisal results for the same inode, but for different hooks, could differ. This patch caches the integrity appraisal results on a per hook basis. Changelog v2: - Rename ima_cache_status() to ima_set_cache_status() - Rename and move get_appraise_status() to ima_get_cache_status() Changelog v0: - include IMA_APPRAISE/APPRAISED_SUBMASK in IMA_DO/DONE_MASK (Dmitry) - Support independent MODULE_CHECK appraise status. - fixed IMA_XXXX_APPRAISE/APPRAISED flags Signed-off-by: Mimi Zohar Signed-off-by: Dmitry Kasatkin --- security/integrity/ima/ima_appraise.c | 71 ++++++++++++++++++++++++++++++----- 1 file changed, 62 insertions(+), 9 deletions(-) (limited to 'security/integrity/ima/ima_appraise.c') diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 8004332ccb8f..2d4becab8918 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -51,6 +51,62 @@ static int ima_fix_xattr(struct dentry *dentry, sizeof(iint->ima_xattr), 0); } +/* Return specific func appraised cached result */ +enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, + int func) +{ + switch(func) { + case MMAP_CHECK: + return iint->ima_mmap_status; + case BPRM_CHECK: + return iint->ima_bprm_status; + case MODULE_CHECK: + return iint->ima_module_status; + case FILE_CHECK: + default: + return iint->ima_file_status; + } +} + +static void ima_set_cache_status(struct integrity_iint_cache *iint, + int func, enum integrity_status status) +{ + switch(func) { + case MMAP_CHECK: + iint->ima_mmap_status = status; + break; + case BPRM_CHECK: + iint->ima_bprm_status = status; + break; + case MODULE_CHECK: + iint->ima_module_status = status; + break; + case FILE_CHECK: + default: + iint->ima_file_status = status; + break; + } +} + +static void ima_cache_flags(struct integrity_iint_cache *iint, int func) +{ + switch(func) { + case MMAP_CHECK: + iint->flags |= (IMA_MMAP_APPRAISED | IMA_APPRAISED); + break; + case BPRM_CHECK: + iint->flags |= (IMA_BPRM_APPRAISED | IMA_APPRAISED); + break; + case MODULE_CHECK: + iint->flags |= (IMA_MODULE_APPRAISED | IMA_APPRAISED); + break; + case FILE_CHECK: + default: + iint->flags |= (IMA_FILE_APPRAISED | IMA_APPRAISED); + break; + } +} + /* * ima_appraise_measurement - appraise file measurement * @@ -59,7 +115,7 @@ static int ima_fix_xattr(struct dentry *dentry, * * Return 0 on success, error code otherwise */ -int ima_appraise_measurement(struct integrity_iint_cache *iint, +int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, struct file *file, const unsigned char *filename) { struct dentry *dentry = file->f_dentry; @@ -75,9 +131,6 @@ int ima_appraise_measurement(struct integrity_iint_cache *iint, if (!inode->i_op->getxattr) return INTEGRITY_UNKNOWN; - if (iint->flags & IMA_APPRAISED) - return iint->ima_status; - rc = vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)&xattr_value, 0, GFP_NOFS); if (rc <= 0) { @@ -99,7 +152,6 @@ int ima_appraise_measurement(struct integrity_iint_cache *iint, cause = "invalid-HMAC"; goto out; } - switch (xattr_value->type) { case IMA_XATTR_DIGEST: if (iint->flags & IMA_DIGSIG_REQUIRED) { @@ -148,9 +200,9 @@ out: integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename, op, cause, rc, 0); } else { - iint->flags |= IMA_APPRAISED; + ima_cache_flags(iint, func); } - iint->ima_status = status; + ima_set_cache_status(iint, func, status); kfree(xattr_value); return status; } @@ -196,10 +248,11 @@ void ima_inode_post_setattr(struct dentry *dentry) must_appraise = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR); iint = integrity_iint_find(inode); if (iint) { + iint->flags &= ~(IMA_APPRAISE | IMA_APPRAISED | + IMA_APPRAISE_SUBMASK | IMA_APPRAISED_SUBMASK | + IMA_ACTION_FLAGS); if (must_appraise) iint->flags |= IMA_APPRAISE; - else - iint->flags &= ~(IMA_APPRAISE | IMA_APPRAISED); } if (!must_appraise) rc = inode->i_op->removexattr(dentry, XATTR_NAME_IMA); -- cgit v1.2.3