diff options
Diffstat (limited to 'security/integrity/ima/ima_main.c')
-rw-r--r-- | security/integrity/ima/ima_main.c | 84 |
1 files changed, 62 insertions, 22 deletions
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index dca44cf7838e..2d31921fbda4 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -168,7 +168,7 @@ void ima_file_free(struct file *file) static int process_measurement(struct file *file, const struct cred *cred, u32 secid, char *buf, loff_t size, int mask, - enum ima_hooks func, int opened) + enum ima_hooks func) { struct inode *inode = file_inode(file); struct integrity_iint_cache *iint = NULL; @@ -294,7 +294,7 @@ static int process_measurement(struct file *file, const struct cred *cred, if (rc == 0 && (action & IMA_APPRAISE_SUBMASK)) { inode_lock(inode); rc = ima_appraise_measurement(func, iint, file, pathname, - xattr_value, xattr_len, opened); + xattr_value, xattr_len); inode_unlock(inode); } if (action & IMA_AUDIT) @@ -338,7 +338,7 @@ int ima_file_mmap(struct file *file, unsigned long prot) if (file && (prot & PROT_EXEC)) { security_task_getsecid(current, &secid); return process_measurement(file, current_cred(), secid, NULL, - 0, MAY_EXEC, MMAP_CHECK, 0); + 0, MAY_EXEC, MMAP_CHECK); } return 0; @@ -364,13 +364,13 @@ int ima_bprm_check(struct linux_binprm *bprm) security_task_getsecid(current, &secid); ret = process_measurement(bprm->file, current_cred(), secid, NULL, 0, - MAY_EXEC, BPRM_CHECK, 0); + MAY_EXEC, BPRM_CHECK); if (ret) return ret; security_cred_getsecid(bprm->cred, &secid); return process_measurement(bprm->file, bprm->cred, secid, NULL, 0, - MAY_EXEC, CREDS_CHECK, 0); + MAY_EXEC, CREDS_CHECK); } /** @@ -383,14 +383,14 @@ int ima_bprm_check(struct linux_binprm *bprm) * 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_file_check(struct file *file, int mask, int opened) +int ima_file_check(struct file *file, int mask) { u32 secid; security_task_getsecid(current, &secid); return process_measurement(file, current_cred(), secid, NULL, 0, mask & (MAY_READ | MAY_WRITE | MAY_EXEC | - MAY_APPEND), FILE_CHECK, opened); + MAY_APPEND), FILE_CHECK); } EXPORT_SYMBOL_GPL(ima_file_check); @@ -429,16 +429,14 @@ void ima_post_path_mknod(struct dentry *dentry) */ int ima_read_file(struct file *file, enum kernel_read_file_id read_id) { - bool sig_enforce = is_module_sig_enforced(); - - if (!file && read_id == READING_MODULE) { - if (!sig_enforce && (ima_appraise & IMA_APPRAISE_MODULES) && - (ima_appraise & IMA_APPRAISE_ENFORCE)) { - pr_err("impossible to appraise a module without a file descriptor. sig_enforce kernel parameter might help\n"); - return -EACCES; /* INTEGRITY_UNKNOWN */ - } - return 0; /* We rely on module signature checking */ - } + /* + * READING_FIRMWARE_PREALLOC_BUFFER + * + * Do devices using pre-allocated memory run the risk of the + * firmware being accessible to the device prior to the completion + * of IMA's signature verification any more than when using two + * buffers? + */ return 0; } @@ -472,14 +470,13 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size, if (!file && read_id == READING_FIRMWARE) { if ((ima_appraise & IMA_APPRAISE_FIRMWARE) && - (ima_appraise & IMA_APPRAISE_ENFORCE)) + (ima_appraise & IMA_APPRAISE_ENFORCE)) { + pr_err("Prevent firmware loading_store.\n"); return -EACCES; /* INTEGRITY_UNKNOWN */ + } return 0; } - if (!file && read_id == READING_MODULE) /* MODULE_SIG_FORCE enabled */ - return 0; - /* permit signed certs */ if (!file && read_id == READING_X509_CERTIFICATE) return 0; @@ -493,7 +490,50 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size, func = read_idmap[read_id] ?: FILE_CHECK; security_task_getsecid(current, &secid); return process_measurement(file, current_cred(), secid, buf, size, - MAY_READ, func, 0); + MAY_READ, func); +} + +/** + * ima_load_data - appraise decision based on policy + * @id: kernel load data caller identifier + * + * Callers of this LSM hook can not measure, appraise, or audit the + * data provided by userspace. Enforce policy rules requring a file + * signature (eg. kexec'ed kernel image). + * + * For permission return 0, otherwise return -EACCES. + */ +int ima_load_data(enum kernel_load_data_id id) +{ + bool sig_enforce; + + if ((ima_appraise & IMA_APPRAISE_ENFORCE) != IMA_APPRAISE_ENFORCE) + return 0; + + switch (id) { + case LOADING_KEXEC_IMAGE: + if (ima_appraise & IMA_APPRAISE_KEXEC) { + pr_err("impossible to appraise a kernel image without a file descriptor; try using kexec_file_load syscall.\n"); + return -EACCES; /* INTEGRITY_UNKNOWN */ + } + break; + case LOADING_FIRMWARE: + if (ima_appraise & IMA_APPRAISE_FIRMWARE) { + pr_err("Prevent firmware sysfs fallback loading.\n"); + return -EACCES; /* INTEGRITY_UNKNOWN */ + } + break; + case LOADING_MODULE: + sig_enforce = is_module_sig_enforced(); + + if (!sig_enforce && (ima_appraise & IMA_APPRAISE_MODULES)) { + pr_err("impossible to appraise a module without a file descriptor. sig_enforce kernel parameter might help\n"); + return -EACCES; /* INTEGRITY_UNKNOWN */ + } + default: + break; + } + return 0; } static int __init init_ima(void) |