diff options
Diffstat (limited to 'security/integrity/ima/ima_main.c')
-rw-r--r-- | security/integrity/ima/ima_main.c | 92 |
1 files changed, 67 insertions, 25 deletions
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 9d96551d0196..391f41751021 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -24,7 +24,6 @@ #include <linux/slab.h> #include <linux/xattr.h> #include <linux/ima.h> -#include <crypto/hash_info.h> #include "ima.h" @@ -154,8 +153,8 @@ void ima_file_free(struct file *file) ima_check_last_writer(iint, inode, file); } -static int process_measurement(struct file *file, int mask, int function, - int opened) +static int process_measurement(struct file *file, char *buf, loff_t size, + int mask, enum ima_hooks func, int opened) { struct inode *inode = file_inode(file); struct integrity_iint_cache *iint = NULL; @@ -163,9 +162,10 @@ static int process_measurement(struct file *file, int mask, int function, char *pathbuf = NULL; const char *pathname = NULL; int rc = -ENOMEM, action, must_appraise; - struct evm_ima_xattr_data *xattr_value = NULL, **xattr_ptr = NULL; + struct evm_ima_xattr_data *xattr_value = NULL; int xattr_len = 0; bool violation_check; + enum hash_algo hash_algo; if (!ima_policy_flag || !S_ISREG(inode->i_mode)) return 0; @@ -174,8 +174,8 @@ static int process_measurement(struct file *file, int mask, int function, * bitmask based on the appraise/audit/measurement policy. * Included is the appraise submask. */ - action = ima_get_action(inode, mask, function); - violation_check = ((function == FILE_CHECK || function == MMAP_CHECK) && + action = ima_get_action(inode, mask, func); + violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) && (ima_policy_flag & IMA_MEASURE)); if (!action && !violation_check) return 0; @@ -184,7 +184,7 @@ static int process_measurement(struct file *file, int mask, int function, /* Is the appraise rule hook specific? */ if (action & IMA_FILE_APPRAISE) - function = FILE_CHECK; + func = FILE_CHECK; inode_lock(inode); @@ -214,16 +214,19 @@ static int process_measurement(struct file *file, int mask, int function, /* Nothing to do, just return existing appraised status */ if (!action) { if (must_appraise) - rc = ima_get_cache_status(iint, function); + rc = ima_get_cache_status(iint, func); goto out_digsig; } template_desc = ima_template_desc_current(); if ((action & IMA_APPRAISE_SUBMASK) || strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0) - xattr_ptr = &xattr_value; + /* read 'security.ima' */ + xattr_len = ima_read_xattr(file->f_path.dentry, &xattr_value); - rc = ima_collect_measurement(iint, file, xattr_ptr, &xattr_len); + hash_algo = ima_get_hash_algo(xattr_value, xattr_len); + + rc = ima_collect_measurement(iint, file, buf, size, hash_algo); if (rc != 0) { if (file->f_flags & O_DIRECT) rc = (iint->flags & IMA_PERMIT_DIRECTIO) ? 0 : -EACCES; @@ -237,7 +240,7 @@ static int process_measurement(struct file *file, int mask, int function, ima_store_measurement(iint, file, pathname, xattr_value, xattr_len); if (action & IMA_APPRAISE_SUBMASK) - rc = ima_appraise_measurement(function, iint, file, pathname, + rc = ima_appraise_measurement(func, iint, file, pathname, xattr_value, xattr_len, opened); if (action & IMA_AUDIT) ima_audit_measurement(iint, pathname); @@ -270,7 +273,8 @@ out: int ima_file_mmap(struct file *file, unsigned long prot) { if (file && (prot & PROT_EXEC)) - return process_measurement(file, MAY_EXEC, MMAP_CHECK, 0); + return process_measurement(file, NULL, 0, MAY_EXEC, + MMAP_CHECK, 0); return 0; } @@ -289,7 +293,8 @@ int ima_file_mmap(struct file *file, unsigned long prot) */ int ima_bprm_check(struct linux_binprm *bprm) { - return process_measurement(bprm->file, MAY_EXEC, BPRM_CHECK, 0); + return process_measurement(bprm->file, NULL, 0, MAY_EXEC, + BPRM_CHECK, 0); } /** @@ -304,24 +309,26 @@ int ima_bprm_check(struct linux_binprm *bprm) */ int ima_file_check(struct file *file, int mask, int opened) { - return process_measurement(file, + return process_measurement(file, NULL, 0, mask & (MAY_READ | MAY_WRITE | MAY_EXEC), FILE_CHECK, opened); } EXPORT_SYMBOL_GPL(ima_file_check); /** - * ima_module_check - based on policy, collect/store/appraise measurement. - * @file: pointer to the file to be measured/appraised + * ima_read_file - pre-measure/appraise hook decision based on policy + * @file: pointer to the file to be measured/appraised/audit + * @read_id: caller identifier * - * Measure/appraise kernel modules based on policy. + * Permit reading a file based on policy. The policy rules are written + * in terms of the policy identifier. Appraising the integrity of + * a file requires a file descriptor. * - * On success return 0. On integrity appraisal error, assuming the file - * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. + * For permission return 0, otherwise return -EACCES. */ -int ima_module_check(struct file *file) +int ima_read_file(struct file *file, enum kernel_read_file_id read_id) { - if (!file) { + if (!file && read_id == READING_MODULE) { #ifndef CONFIG_MODULE_SIG_FORCE if ((ima_appraise & IMA_APPRAISE_MODULES) && (ima_appraise & IMA_APPRAISE_ENFORCE)) @@ -329,18 +336,53 @@ int ima_module_check(struct file *file) #endif return 0; /* We rely on module signature checking */ } - return process_measurement(file, MAY_EXEC, MODULE_CHECK, 0); + return 0; } -int ima_fw_from_file(struct file *file, char *buf, size_t size) +static int read_idmap[READING_MAX_ID] = { + [READING_FIRMWARE] = FIRMWARE_CHECK, + [READING_MODULE] = MODULE_CHECK, + [READING_KEXEC_IMAGE] = KEXEC_KERNEL_CHECK, + [READING_KEXEC_INITRAMFS] = KEXEC_INITRAMFS_CHECK, + [READING_POLICY] = POLICY_CHECK +}; + +/** + * ima_post_read_file - in memory collect/appraise/audit measurement + * @file: pointer to the file to be measured/appraised/audit + * @buf: pointer to in memory file contents + * @size: size of in memory file contents + * @read_id: caller identifier + * + * Measure/appraise/audit in memory file based on policy. Policy rules + * are written in terms of a policy identifier. + * + * On success return 0. On integrity appraisal error, assuming the file + * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. + */ +int ima_post_read_file(struct file *file, void *buf, loff_t size, + enum kernel_read_file_id read_id) { - if (!file) { + enum ima_hooks func; + + if (!file && read_id == READING_FIRMWARE) { if ((ima_appraise & IMA_APPRAISE_FIRMWARE) && (ima_appraise & IMA_APPRAISE_ENFORCE)) return -EACCES; /* INTEGRITY_UNKNOWN */ return 0; } - return process_measurement(file, MAY_EXEC, FIRMWARE_CHECK, 0); + + if (!file && read_id == READING_MODULE) /* MODULE_SIG_FORCE enabled */ + return 0; + + if (!file || !buf || size == 0) { /* should never happen */ + if (ima_appraise & IMA_APPRAISE_ENFORCE) + return -EACCES; + return 0; + } + + func = read_idmap[read_id] ?: FILE_CHECK; + return process_measurement(file, buf, size, MAY_READ, func, 0); } static int __init init_ima(void) |