
From: Zhang Tianxing <zhangtianxing3@huawei.com> hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4O25G CVE: NA -------------------------------- This reverts commit 27229fcf200a646b1a795e9c0ac655a3f1bfda42. Signed-off-by: Zhang Tianxing <zhangtianxing3@huawei.com> Acked-by: Xie XiuQi <xiexiuqi@huawei.com> Acked-by: Xiu Jianfeng<xiujianfeng@huawei.com> Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com> --- include/linux/ima.h | 11 - kernel/kexec_file.c | 7 - security/integrity/ima/ima.h | 12 +- security/integrity/ima/ima_api.c | 2 +- security/integrity/ima/ima_appraise.c | 95 ++--- security/integrity/ima/ima_asymmetric_keys.c | 13 +- security/integrity/ima/ima_digest_list.c | 4 +- security/integrity/ima/ima_fs.c | 6 +- security/integrity/ima/ima_init.c | 7 +- security/integrity/ima/ima_main.c | 240 ++++--------- security/integrity/ima/ima_ns.c | 3 - security/integrity/ima/ima_policy.c | 345 ++++++++----------- security/integrity/ima/ima_queue_keys.c | 10 +- security/security.c | 2 +- 14 files changed, 250 insertions(+), 507 deletions(-) diff --git a/include/linux/ima.h b/include/linux/ima.h index d7b2864d7d7c..f5683756f2b5 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -37,8 +37,6 @@ extern int ima_post_read_file(struct file *file, void *buf, loff_t size, extern void ima_post_path_mknod(struct dentry *dentry); extern int ima_file_hash(struct file *file, char *buf, size_t buf_size); extern void ima_kexec_cmdline(int kernel_fd, const void *buf, int size); -extern void ima_inode_free(struct inode *inode); -extern bool ima_is_root_namespace(void); #ifdef CONFIG_IMA_KEXEC extern void ima_add_kexec_buffer(struct kimage *image); @@ -130,15 +128,6 @@ static inline int ima_file_hash(struct file *file, char *buf, size_t buf_size) } static inline void ima_kexec_cmdline(int kernel_fd, const void *buf, int size) {} - -static inline void ima_inode_free(struct inode *inode) -{ -} - -static inline bool ima_is_root_namespace(void) -{ - return true; -} #endif /* CONFIG_IMA */ #ifndef CONFIG_IMA_KEXEC diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index d407f7983020..33400ff051a8 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -362,13 +362,6 @@ SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd, if (!capable(CAP_SYS_BOOT) || kexec_load_disabled) return -EPERM; - /* Allow only from the initial IMA namespace, so that the user can't - * spawn a new IMA namespace with the empty policy and circumvent the - * appraisal protection. - */ - if (!ima_is_root_namespace()) - return -EPERM; - /* Make sure we have a legal set of flags */ if (flags != (flags & KEXEC_FILE_FLAGS)) return -EINVAL; diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 1fae3709266f..8b59e03ec849 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -44,11 +44,15 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10 }; #define NR_BANKS(chip) ((chip != NULL) ? chip->nr_allocated_banks : 0) +/* current content of the policy */ +extern int ima_policy_flag; + /* set during initialization */ extern int ima_hash_algo; extern int ima_sha1_idx __ro_after_init; extern int ima_hash_algo_idx __ro_after_init; extern int ima_extra_slots __ro_after_init; +extern int ima_appraise; extern struct tpm_chip *ima_tpm_chip; extern int ima_digest_list_pcr; extern bool ima_plus_standard_pcr; @@ -65,8 +69,6 @@ struct ima_policy_setup_data { int ima_appraise; bool ima_use_secure_boot; bool ima_use_appraise_tcb; - bool ima_use_appraise_exec_tcb; - bool ima_use_appraise_exec_immutable; }; /* IMA event related data */ @@ -400,9 +402,6 @@ struct ima_policy_data { int temp_ima_appraise; }; -extern struct list_head ima_ns_list; -extern struct rw_semaphore ima_ns_list_lock; - extern struct ima_policy_data init_policy_data; extern struct ima_policy_setup_data init_policy_setup_data; @@ -416,9 +415,6 @@ static inline struct ima_namespace *get_current_ns(void) { return current->nsproxy->ima_ns; } - -void ima_delete_ns_rules(struct ima_policy_data *policy_data, - bool is_root_ns); #else static inline int __init ima_init_namespace(void) { diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 743b9337d9e5..b4347eac9c85 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -212,7 +212,7 @@ int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid, { int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE | IMA_HASH; - flags &= ima_ns->policy_data->ima_policy_flag; + flags &= ima_policy_flag; return ima_match_policy(inode, cred, secid, func, mask, flags, pcr, template_desc, keyring, ima_ns); diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 9d041e3deef2..9213c012cbe4 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -21,10 +21,18 @@ static bool ima_appraise_req_evm __ro_after_init; int ima_default_appraise_setup(const char *str, struct ima_policy_setup_data *setup_data) +{ + /* Currently unused. It will be implemented after namespacing ima + * policy, when global variables are removed. + */ + return 1; +} + +static int __init default_appraise_setup(char *str) { #ifdef CONFIG_IMA_APPRAISE_BOOTPARAM bool sb_state = arch_ima_get_secureboot(); - int appraisal_state = setup_data->ima_appraise; + int appraisal_state = ima_appraise; if (strncmp(str, "off", 3) == 0) appraisal_state = 0; @@ -44,7 +52,7 @@ int ima_default_appraise_setup(const char *str, pr_info("Secure boot enabled: ignoring ima_appraise=%s option", str); } else { - setup_data->ima_appraise = appraisal_state; + ima_appraise = appraisal_state; } #endif if (strcmp(str, "enforce-evm") == 0 || @@ -53,11 +61,6 @@ int ima_default_appraise_setup(const char *str, return 1; } -static int __init default_appraise_setup(char *str) -{ - return ima_default_appraise_setup(str, &init_policy_setup_data); -} - __setup("ima_appraise=", default_appraise_setup); static bool ima_appraise_no_metadata __ro_after_init; @@ -84,10 +87,7 @@ __setup("ima_appraise_digest_list=", appraise_digest_list_setup); */ bool is_ima_appraise_enabled(const struct ima_namespace *ima_ns) { - if (!ima_ns) - return false; - - return ima_ns->policy_data->ima_appraise & IMA_APPRAISE_ENFORCE; + return ima_appraise & IMA_APPRAISE_ENFORCE; } /* @@ -95,18 +95,18 @@ bool is_ima_appraise_enabled(const struct ima_namespace *ima_ns) * * Return 1 to appraise or hash */ -int ima_must_appraise(struct inode *inode, int mask, - enum ima_hooks func, struct ima_namespace *ima_ns) +int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func, + struct ima_namespace *ima_ns) { u32 secid; - if (!ima_ns->policy_data->ima_appraise) + if (!ima_appraise) return 0; security_task_getsecid(current, &secid); return ima_match_policy(inode, current_cred(), secid, func, mask, IMA_APPRAISE | IMA_HASH, NULL, NULL, NULL, - ima_ns); + NULL); } static int ima_fix_xattr(struct dentry *dentry, @@ -352,7 +352,7 @@ int ima_check_blacklist(struct integrity_iint_cache *iint, if ((rc == -EPERM) && (iint->flags & IMA_MEASURE)) process_buffer_measurement(NULL, digest, digestsize, "blacklisted-hash", NONE, - pcr, NULL, ima_ns); + pcr, NULL, NULL); } return rc; @@ -381,7 +381,6 @@ int ima_appraise_measurement(enum ima_hooks func, int rc = xattr_len, rc_evm; char _buf[sizeof(struct evm_ima_xattr_data) + 1 + SHA512_DIGEST_SIZE]; bool try_modsig = iint->flags & IMA_MODSIG_ALLOWED && modsig; - struct ima_namespace *ima_ns = get_current_ns(); /* If not appraising a modsig, we need an xattr. */ if (!(inode->i_opflags & IOP_XATTR) && !try_modsig) @@ -510,8 +509,7 @@ int ima_appraise_measurement(enum ima_hooks func, op, cause, rc, 0); } else if (status != INTEGRITY_PASS) { /* Fix mode, but don't replace file signatures. */ - if ((ima_ns->policy_data->ima_appraise & IMA_APPRAISE_FIX) && - !try_modsig && + if ((ima_appraise & IMA_APPRAISE_FIX) && !try_modsig && (!xattr_value || xattr_value->type != EVM_IMA_XATTR_DIGSIG)) { if (!ima_fix_xattr(dentry, iint)) @@ -576,30 +574,18 @@ void ima_inode_post_setattr(struct dentry *dentry) struct inode *inode = d_backing_inode(dentry); struct integrity_iint_cache *iint; int action; - struct ima_namespace *ima_ns; - if (!S_ISREG(inode->i_mode) || - !(inode->i_opflags & IOP_XATTR)) + if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode) + || !(inode->i_opflags & IOP_XATTR)) return; - down_read(&ima_ns_list_lock); - list_for_each_entry(ima_ns, &ima_ns_list, list) { - if (atomic_read(&ima_ns->inactive)) - continue; - if (!(ima_ns->policy_data->ima_policy_flag & IMA_APPRAISE)) - continue; - - action = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR, - ima_ns); - iint = integrity_iint_rb_find(ima_ns->iint_tree, inode); - if (iint) { - set_bit(IMA_CHANGE_ATTR, &iint->atomic_flags); - if (!action) - clear_bit(IMA_UPDATE_XATTR, - &iint->atomic_flags); - } + action = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR, NULL); + iint = integrity_iint_find(inode); + if (iint) { + set_bit(IMA_CHANGE_ATTR, &iint->atomic_flags); + if (!action) + clear_bit(IMA_UPDATE_XATTR, &iint->atomic_flags); } - up_read(&ima_ns_list_lock); } /* @@ -621,30 +607,19 @@ static int ima_protect_xattr(struct dentry *dentry, const char *xattr_name, static void ima_reset_appraise_flags(struct inode *inode, int digsig) { struct integrity_iint_cache *iint; - struct ima_namespace *ima_ns; - if (!S_ISREG(inode->i_mode)) + if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)) return; - down_read(&ima_ns_list_lock); - list_for_each_entry(ima_ns, &ima_ns_list, list) { - if (atomic_read(&ima_ns->inactive)) - continue; - if (!(ima_ns->policy_data->ima_policy_flag & IMA_APPRAISE)) - continue; - - iint = integrity_iint_rb_find(ima_ns->iint_tree, inode); - if (!iint) - continue; - - iint->measured_pcrs = 0; - set_bit(IMA_CHANGE_XATTR, &iint->atomic_flags); - if (digsig) - set_bit(IMA_DIGSIG, &iint->atomic_flags); - else - clear_bit(IMA_DIGSIG, &iint->atomic_flags); - } - up_read(&ima_ns_list_lock); + iint = integrity_iint_find(inode); + if (!iint) + return; + iint->measured_pcrs = 0; + set_bit(IMA_CHANGE_XATTR, &iint->atomic_flags); + if (digsig) + set_bit(IMA_DIGSIG, &iint->atomic_flags); + else + clear_bit(IMA_DIGSIG, &iint->atomic_flags); } int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, diff --git a/security/integrity/ima/ima_asymmetric_keys.c b/security/integrity/ima/ima_asymmetric_keys.c index b3330a0a1481..58aa56b0422d 100644 --- a/security/integrity/ima/ima_asymmetric_keys.c +++ b/security/integrity/ima/ima_asymmetric_keys.c @@ -29,16 +29,6 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key, unsigned long flags, bool create) { bool queued = false; - /* Measure the keys according to the current ima namespace's policy - * rules. If the new ima namespace with empty policy is created to hide - * the log, parent can join it to inspect the log until the child - * namespace exists. After its destruction, log can be accessed only - * by the processes from the initial ima namespace that see all - * measurement list entries. If this is a problem, maybe the solution - * is to track in which namespaces the key was measured and re-measure - * it when necessary. - */ - struct ima_namespace *ima_ns = get_current_ns(); /* Only asymmetric keys are handled by this hook. */ if (key->type != &key_type_asymmetric) @@ -70,5 +60,6 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key, */ process_buffer_measurement(NULL, payload, payload_len, keyring->description, KEY_CHECK, 0, - keyring->description, ima_ns); + keyring->description, + NULL); } diff --git a/security/integrity/ima/ima_digest_list.c b/security/integrity/ima/ima_digest_list.c index 2d7148ff09c1..dd6dbdbbc7dd 100644 --- a/security/integrity/ima/ima_digest_list.c +++ b/security/integrity/ima/ima_digest_list.c @@ -173,7 +173,7 @@ int ima_parse_compact_list(loff_t size, void *buf, int op) size_t digest_len; int ret = 0, i; - if (!(ima_digest_list_actions & init_policy_data.ima_policy_flag)) + if (!(ima_digest_list_actions & ima_policy_flag)) return -EACCES; while (bufp < bufendp) { @@ -394,7 +394,7 @@ void __init ima_load_digest_lists(void) .ctx.actor = load_digest_list, }; - if (!(ima_digest_list_actions & init_policy_data.ima_policy_flag)) + if (!(ima_digest_list_actions & ima_policy_flag)) return; ret = kern_path(CONFIG_IMA_DIGEST_LISTS_DIR, 0, &path); diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index bf1d464620f7..64f5b0997760 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -369,7 +369,6 @@ static ssize_t ima_write_data(struct file *file, const char __user *buf, ssize_t result; struct dentry *dentry = file_dentry(file); int i; - struct ima_namespace *ima_ns = get_current_ns(); /* No partial writes. */ result = -EINVAL; @@ -405,7 +404,7 @@ static ssize_t ima_write_data(struct file *file, const char __user *buf, if (data[0] == '/') { result = ima_read_sfs_file(data, dentry); } else if (dentry == ima_policy) { - if (ima_ns->policy_data->ima_appraise & IMA_APPRAISE_POLICY) { + if (ima_appraise & IMA_APPRAISE_POLICY) { pr_err("signed policy file (specified " "as an absolute pathname) required\n"); integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL, @@ -520,7 +519,6 @@ static int ima_release_data_upload(struct inode *inode, struct file *file) struct dentry *dentry = file_dentry(file); const char *cause = valid_policy ? "completed" : "failed"; enum ima_fs_flags flag = ima_get_dentry_flag(dentry); - struct ima_namespace *ima_ns = get_current_ns(); if ((file->f_flags & O_ACCMODE) == O_RDONLY) return seq_release(inode, file); @@ -533,7 +531,7 @@ static int ima_release_data_upload(struct inode *inode, struct file *file) return 0; } - if (valid_policy && ima_check_policy(ima_ns) < 0) { + if (valid_policy && ima_check_policy(NULL) < 0) { cause = "failed"; valid_policy = 0; } diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index dea0251142fd..3b8839b97a98 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -118,16 +118,15 @@ static int __init ima_add_boot_aggregate(void) #ifdef CONFIG_IMA_LOAD_X509 void __init ima_load_x509(void) { - int unset_flags = - init_ima_ns.policy_data->ima_policy_flag & IMA_APPRAISE; + int unset_flags = ima_policy_flag & IMA_APPRAISE; - init_ima_ns.policy_data->ima_policy_flag &= ~unset_flags; + ima_policy_flag &= ~unset_flags; integrity_load_x509(INTEGRITY_KEYRING_IMA, CONFIG_IMA_X509_PATH); /* load also EVM key to avoid appraisal */ evm_load_x509(); - init_ima_ns.policy_data->ima_policy_flag |= unset_flags; + ima_policy_flag |= unset_flags; } #endif diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 7986dfb3e5d6..9bbd716bff99 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -30,6 +30,12 @@ #include "ima.h" #include "ima_digest_list.h" +#ifdef CONFIG_IMA_APPRAISE +int ima_appraise = IMA_APPRAISE_ENFORCE; +#else +int ima_appraise; +#endif + int ima_hash_algo = HASH_ALGO_SHA1; /* Actions (measure/appraisal) for which digest lists can be used */ @@ -128,8 +134,7 @@ static void ima_rdwr_violation_check(struct file *file, if (mode & FMODE_WRITE) { if (atomic_read(&inode->i_readcount) && IS_IMA(inode)) { if (!iint) - iint = integrity_iint_rb_find(ima_ns->iint_tree, - inode); + iint = integrity_iint_find(inode); /* IMA_MEASURE is set from reader side */ if (iint && test_bit(IMA_MUST_MEASURE, &iint->atomic_flags)) @@ -209,38 +214,11 @@ static int ima_read_xattr(struct dentry *dentry, return ret; } -static void ima_check_active_ns(struct ima_namespace *current_ima_ns, - struct inode *inode) -{ - struct ima_namespace *ima_ns; - struct integrity_iint_cache *iint; - - down_read(&ima_ns_list_lock); - list_for_each_entry(ima_ns, &ima_ns_list, list) { - if (atomic_read(&ima_ns->inactive)) - continue; - if ((ima_ns == current_ima_ns) || - !ima_ns->policy_data->ima_policy_flag) - continue; - - iint = integrity_iint_rb_find(ima_ns->iint_tree, inode); - if (!iint) - continue; - - mutex_lock(&iint->mutex); - iint->flags &= ~IMA_DONE_MASK; - iint->measured_pcrs = 0; - mutex_unlock(&iint->mutex); - } - up_read(&ima_ns_list_lock); -} - static void ima_check_last_writer(struct integrity_iint_cache *iint, struct inode *inode, struct file *file) { fmode_t mode = file->f_mode; bool update; - struct ima_namespace *ima_ns = (struct ima_namespace *)file->f_ima; if (!(mode & FMODE_WRITE)) return; @@ -254,9 +232,6 @@ static void ima_check_last_writer(struct integrity_iint_cache *iint, (iint->flags & IMA_NEW_FILE)) { iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE); iint->measured_pcrs = 0; - - ima_check_active_ns(ima_ns, inode); - if (update) ima_update_xattr(iint, file); } @@ -306,10 +281,10 @@ void ima_file_free(struct file *file) if (unlikely(!(file->f_mode & FMODE_OPENED))) goto out; - if (!ima_ns->policy_data->ima_policy_flag || !S_ISREG(inode->i_mode)) + if (!ima_policy_flag || !S_ISREG(inode->i_mode)) goto out; - iint = integrity_iint_rb_find(ima_ns->iint_tree, inode); + iint = integrity_iint_find(inode); if (!iint) goto out; @@ -318,10 +293,10 @@ void ima_file_free(struct file *file) put_ima_ns(ima_ns); } -static int process_ns_measurement(struct file *file, const struct cred *cred, - u32 secid, char *buf, loff_t size, int mask, - enum ima_hooks func, - struct ima_namespace *ima_ns) +static int process_measurement(struct file *file, const struct cred *cred, + u32 secid, char *buf, loff_t size, int mask, + enum ima_hooks func, + struct ima_namespace *ima_ns) { struct inode *inode = file_inode(file); struct integrity_iint_cache *iint = NULL; @@ -337,9 +312,8 @@ static int process_ns_measurement(struct file *file, const struct cred *cred, int xattr_len = 0; bool violation_check; enum hash_algo hash_algo; - struct ima_namespace *current_ima_ns = get_current_ns(); - if (!ima_ns->policy_data->ima_policy_flag) + if (!ima_policy_flag || !S_ISREG(inode->i_mode)) return 0; /* Return an IMA_MEASURE, IMA_APPRAISE, IMA_AUDIT action @@ -349,8 +323,7 @@ static int process_ns_measurement(struct file *file, const struct cred *cred, action = ima_get_action(inode, cred, secid, mask, func, &pcr, &template_desc, NULL, ima_ns); violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) && - (ima_ns->policy_data->ima_policy_flag & - IMA_MEASURE)); + (ima_policy_flag & IMA_MEASURE)); if (!action && !violation_check) return 0; @@ -363,7 +336,7 @@ static int process_ns_measurement(struct file *file, const struct cred *cred, inode_lock(inode); if (action) { - iint = integrity_inode_rb_get(ima_ns->iint_tree, inode); + iint = integrity_inode_get(inode); if (!iint) rc = -ENOMEM; } @@ -378,8 +351,6 @@ static int process_ns_measurement(struct file *file, const struct cred *cred, goto out; if (!action) goto out; - if (ima_ns != current_ima_ns) - goto out; mutex_lock(&iint->mutex); @@ -510,8 +481,7 @@ static int process_ns_measurement(struct file *file, const struct cred *cred, if (pathbuf) __putname(pathbuf); if (must_appraise) { - if (rc && - (ima_ns->policy_data->ima_appraise & IMA_APPRAISE_ENFORCE)) + if (rc && (ima_appraise & IMA_APPRAISE_ENFORCE)) return -EACCES; if (file->f_mode & FMODE_WRITE) set_bit(IMA_UPDATE_XATTR, &iint->atomic_flags); @@ -519,32 +489,6 @@ static int process_ns_measurement(struct file *file, const struct cred *cred, return 0; } -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 ret; - struct ima_namespace *ima_ns; - struct inode *inode = file_inode(file); - - if (!S_ISREG(inode->i_mode)) - return 0; - - down_read(&ima_ns_list_lock); - list_for_each_entry(ima_ns, &ima_ns_list, list) { - if (atomic_read(&ima_ns->inactive)) - continue; - - ret = process_ns_measurement(file, cred, secid, buf, size, mask, - func, ima_ns); - if (ret != 0) - break; - } - up_read(&ima_ns_list_lock); - - return ret; -} - /** * ima_file_mmap - based on policy, collect/store measurement. * @file: pointer to the file to be measured (May be NULL) @@ -563,7 +507,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, MAY_EXEC, MMAP_CHECK, NULL); } return 0; @@ -583,7 +527,6 @@ int ima_file_mmap(struct file *file, unsigned long prot) */ int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot) { - struct ima_namespace *ima_ns = get_current_ns(); struct ima_template_desc *template; struct file *file = vma->vm_file; char filename[NAME_MAX]; @@ -596,15 +539,14 @@ int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot) int pcr; /* Is mprotect making an mmap'ed file executable? */ - if (!(ima_ns->policy_data->ima_policy_flag & IMA_APPRAISE) || - !vma->vm_file || !(prot & PROT_EXEC) || - (vma->vm_flags & VM_EXEC)) + if (!(ima_policy_flag & IMA_APPRAISE) || !vma->vm_file || + !(prot & PROT_EXEC) || (vma->vm_flags & VM_EXEC)) return 0; security_task_getsecid(current, &secid); inode = file_inode(vma->vm_file); action = ima_get_action(inode, current_cred(), secid, MAY_EXEC, - MMAP_CHECK, &pcr, &template, 0, ima_ns); + MMAP_CHECK, &pcr, &template, 0, NULL); /* Is the mmap'ed file in policy? */ if (!(action & (IMA_MEASURE | IMA_APPRAISE_SUBMASK))) @@ -643,13 +585,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); + MAY_EXEC, BPRM_CHECK, NULL); if (ret) return ret; security_cred_getsecid(bprm->cred, &secid); return process_measurement(bprm->file, bprm->cred, secid, NULL, 0, - MAY_EXEC, CREDS_CHECK); + MAY_EXEC, CREDS_CHECK, NULL); } /** @@ -670,7 +612,7 @@ int ima_file_check(struct file *file, int mask) security_task_getsecid(current, &secid); rc = process_measurement(file, current_cred(), secid, NULL, 0, mask & (MAY_READ | MAY_WRITE | MAY_EXEC | - MAY_APPEND), FILE_CHECK); + MAY_APPEND), FILE_CHECK, NULL); if (ima_current_is_parser() && !rc) ima_check_measured_appraised(file); return rc; @@ -679,7 +621,7 @@ EXPORT_SYMBOL_GPL(ima_file_check); /** * ima_file_hash - return the stored measurement if a file has been hashed and - * is in the iint cache of the current IMA namespace. + * is in the iint cache. * @file: pointer to the file * @buf: buffer in which to store the hash * @buf_size: length of the buffer @@ -697,7 +639,6 @@ EXPORT_SYMBOL_GPL(ima_file_check); */ int ima_file_hash(struct file *file, char *buf, size_t buf_size) { - struct ima_namespace *ima_ns = get_current_ns(); struct inode *inode; struct integrity_iint_cache *iint; int hash_algo; @@ -705,11 +646,11 @@ int ima_file_hash(struct file *file, char *buf, size_t buf_size) if (!file) return -EINVAL; - if (!ima_ns->policy_data->ima_policy_flag) + if (!ima_policy_flag) return -EOPNOTSUPP; inode = file_inode(file); - iint = integrity_iint_rb_find(ima_ns->iint_tree, inode); + iint = integrity_iint_find(inode); if (!iint) return -EOPNOTSUPP; @@ -747,30 +688,21 @@ EXPORT_SYMBOL_GPL(ima_file_hash); */ void ima_post_create_tmpfile(struct inode *inode) { - struct ima_namespace *ima_ns; struct integrity_iint_cache *iint; int must_appraise; - down_read(&ima_ns_list_lock); - list_for_each_entry(ima_ns, &ima_ns_list, list) { - if (atomic_read(&ima_ns->inactive)) - continue; - - must_appraise = ima_must_appraise(inode, MAY_ACCESS, - FILE_CHECK, ima_ns); - if (!must_appraise) - continue; + must_appraise = ima_must_appraise(inode, MAY_ACCESS, FILE_CHECK, NULL); + if (!must_appraise) + return; - /* Nothing to do if we can't allocate memory */ - iint = integrity_inode_rb_get(ima_ns->iint_tree, inode); - if (!iint) - continue; + /* Nothing to do if we can't allocate memory */ + iint = integrity_inode_get(inode); + if (!iint) + return; - /* needed for writing the security xattrs */ - set_bit(IMA_UPDATE_XATTR, &iint->atomic_flags); - iint->ima_file_status = INTEGRITY_PASS; - } - up_read(&ima_ns_list_lock); + /* needed for writing the security xattrs */ + set_bit(IMA_UPDATE_XATTR, &iint->atomic_flags); + iint->ima_file_status = INTEGRITY_PASS; } /** @@ -782,30 +714,21 @@ void ima_post_create_tmpfile(struct inode *inode) */ void ima_post_path_mknod(struct dentry *dentry) { - struct ima_namespace *ima_ns; struct integrity_iint_cache *iint; struct inode *inode = dentry->d_inode; int must_appraise; - down_read(&ima_ns_list_lock); - list_for_each_entry(ima_ns, &ima_ns_list, list) { - if (atomic_read(&ima_ns->inactive)) - continue; - - must_appraise = ima_must_appraise(inode, MAY_ACCESS, - FILE_CHECK, ima_ns); - if (!must_appraise) - continue; + must_appraise = ima_must_appraise(inode, MAY_ACCESS, FILE_CHECK, NULL); + if (!must_appraise) + return; - /* Nothing to do if we can't allocate memory */ - iint = integrity_inode_rb_get(ima_ns->iint_tree, inode); - if (!iint) - continue; + /* Nothing to do if we can't allocate memory */ + iint = integrity_inode_get(inode); + if (!iint) + return; - /* needed for re-opening empty files */ - iint->flags |= IMA_NEW_FILE; - } - up_read(&ima_ns_list_lock); + /* needed for re-opening empty files */ + iint->flags |= IMA_NEW_FILE; } /** @@ -846,7 +769,7 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id, func = read_idmap[read_id] ?: FILE_CHECK; security_task_getsecid(current, &secid); return process_measurement(file, current_cred(), secid, NULL, - 0, MAY_READ, func); + 0, MAY_READ, func, NULL); } const int read_idmap[READING_MAX_ID] = { @@ -876,14 +799,13 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size, { enum ima_hooks func; u32 secid; - struct ima_namespace *ima_ns = get_current_ns(); /* permit signed certs */ if (!file && read_id == READING_X509_CERTIFICATE) return 0; if (!file || !buf || size == 0) { /* should never happen */ - if (ima_ns->policy_data->ima_appraise & IMA_APPRAISE_ENFORCE) + if (ima_appraise & IMA_APPRAISE_ENFORCE) return -EACCES; return 0; } @@ -891,7 +813,7 @@ 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); + MAY_READ, func, NULL); } /** @@ -909,16 +831,9 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size, int ima_load_data(enum kernel_load_data_id id, bool contents) { bool ima_enforce, sig_enforce; - struct ima_namespace *ima_ns = get_current_ns(); - - if (ima_ns != &init_ima_ns) { - pr_err("Prevent data loading in IMA namespaces other than the root\n"); - return -EACCES; - } ima_enforce = - (ima_ns->policy_data->ima_appraise & IMA_APPRAISE_ENFORCE) == - IMA_APPRAISE_ENFORCE; + (ima_appraise & IMA_APPRAISE_ENFORCE) == IMA_APPRAISE_ENFORCE; switch (id) { case LOADING_KEXEC_IMAGE: @@ -928,16 +843,13 @@ int ima_load_data(enum kernel_load_data_id id, bool contents) return -EACCES; } - if (ima_enforce && - (ima_ns->policy_data->ima_appraise & IMA_APPRAISE_KEXEC)) { + if (ima_enforce && (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_enforce && - (ima_ns->policy_data->ima_appraise & - IMA_APPRAISE_FIRMWARE) && !contents) { + if (ima_enforce && (ima_appraise & IMA_APPRAISE_FIRMWARE) && !contents) { pr_err("Prevent firmware sysfs fallback loading.\n"); return -EACCES; /* INTEGRITY_UNKNOWN */ } @@ -945,10 +857,8 @@ int ima_load_data(enum kernel_load_data_id id, bool contents) case LOADING_MODULE: sig_enforce = is_module_sig_enforced(); - if (ima_enforce && - (!sig_enforce && - (ima_ns->policy_data->ima_appraise & - IMA_APPRAISE_MODULES))) { + if (ima_enforce && (!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 */ } @@ -975,14 +885,9 @@ int ima_post_load_data(char *buf, loff_t size, enum kernel_load_data_id load_id, char *description) { - struct ima_namespace *ima_ns = get_current_ns(); - if (load_id == LOADING_FIRMWARE) { - if (WARN_ON(ima_ns != &init_ima_ns)) - return -EACCES; - - if ((ima_ns->policy_data->ima_appraise & IMA_APPRAISE_FIRMWARE) && - (ima_ns->policy_data->ima_appraise & IMA_APPRAISE_ENFORCE)) { + if ((ima_appraise & IMA_APPRAISE_FIRMWARE) && + (ima_appraise & IMA_APPRAISE_ENFORCE)) { pr_err("Prevent firmware loading_store.\n"); return -EACCES; /* INTEGRITY_UNKNOWN */ } @@ -1001,7 +906,6 @@ int ima_post_load_data(char *buf, loff_t size, * @func: IMA hook * @pcr: pcr to extend the measurement * @keyring: keyring name to determine the action to be performed - * @ima_ns: pointer to the IMA namespace in consideration * * Based on policy, the buffer is measured into the ima log. */ @@ -1027,7 +931,7 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size, int action = 0; u32 secid; - if (!ima_ns->policy_data->ima_policy_flag) + if (!ima_policy_flag) return; /* @@ -1040,7 +944,7 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size, if (func) { security_task_getsecid(current, &secid); action = ima_get_action(inode, current_cred(), secid, 0, func, - &pcr, &template, keyring, ima_ns); + &pcr, &template, keyring, NULL); if (!(action & IMA_MEASURE)) return; } @@ -1103,11 +1007,6 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size, void ima_kexec_cmdline(int kernel_fd, const void *buf, int size) { struct fd f; - struct ima_namespace *ima_ns = get_current_ns(); - - /* Currently allowed only from the root IMA namespace */ - if (WARN_ON(ima_ns != &init_ima_ns)) - return; if (!buf || !size) return; @@ -1118,31 +1017,10 @@ void ima_kexec_cmdline(int kernel_fd, const void *buf, int size) process_buffer_measurement(file_inode(f.file), buf, size, "kexec-cmdline", KEXEC_CMDLINE, 0, NULL, - ima_ns); + NULL); fdput(f); } -void ima_inode_free(struct inode *inode) -{ - struct ima_namespace *ima_ns; - - if (!IS_IMA(inode)) - return; - - down_read(&ima_ns_list_lock); - list_for_each_entry(ima_ns, &ima_ns_list, list) { - if (atomic_read(&ima_ns->inactive)) - continue; - integrity_inode_rb_free(ima_ns->iint_tree, inode); - } - up_read(&ima_ns_list_lock); -} - -bool ima_is_root_namespace(void) -{ - return get_current_ns() == &init_ima_ns; -} - static int __init init_ima(void) { int error; diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c index 04aa50473971..226a53279f71 100644 --- a/security/integrity/ima/ima_ns.c +++ b/security/integrity/ima/ima_ns.c @@ -181,14 +181,11 @@ int __init ima_init_namespace(void) static void destroy_ima_ns(struct ima_namespace *ns) { - bool is_init_ns = (ns == &init_ima_ns); - dec_ima_namespaces(ns->ucounts); put_user_ns(ns->user_ns); ns_free_inum(&ns->ns); integrity_iint_tree_free(ns->iint_tree); kfree(ns->iint_tree); - ima_delete_ns_rules(ns->policy_data, is_init_ns); kfree(ns->policy_data); kfree(ns); } diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 0ab91cb31121..ebb4721032d4 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -49,6 +49,8 @@ #define INVALID_PCR(a) (((a) < 0) || \ (a) >= (sizeof_field(struct integrity_iint_cache, measured_pcrs) * 8)) +int ima_policy_flag; +static int temp_ima_appraise; static int build_ima_appraise __ro_after_init; #define MAX_LSM_RULES 6 @@ -223,11 +225,16 @@ static struct ima_rule_entry ima_parser_appraise_rule __ro_after_init = { .flags = IMA_PARSER | IMA_DIGSIG_REQUIRED }; -/* Number of architecture specific rules found */ -static int arch_entries_size __ro_after_init; /* An array of architecture specific rules */ static struct ima_rule_entry *arch_policy_entry __ro_after_init; +static LIST_HEAD(ima_default_rules); +static LIST_HEAD(ima_policy_rules); +static LIST_HEAD(ima_temp_rules); +static struct list_head *ima_rules = &ima_default_rules; + +static int ima_policy __initdata; + struct ima_policy_setup_data init_policy_setup_data = { #ifdef CONFIG_IMA_APPRAISE .ima_appraise = IMA_APPRAISE_ENFORCE, @@ -237,25 +244,31 @@ struct ima_policy_data init_policy_data = { .ima_default_rules = LIST_HEAD_INIT(init_policy_data.ima_default_rules), .ima_policy_rules = LIST_HEAD_INIT(init_policy_data.ima_policy_rules), .ima_temp_rules = LIST_HEAD_INIT(init_policy_data.ima_temp_rules), - .ima_rules = &init_policy_data.ima_default_rules, }; int ima_default_measure_policy_setup(const char *str, struct ima_policy_setup_data *setup_data) { - if (setup_data->ima_policy) - return 1; - - setup_data->ima_policy = ORIGINAL_TCB; + /* Currently unused. It will be implemented after namespacing ima + * policy, when global variables are removed. + */ return 1; } static int __init default_measure_policy_setup(char *str) { - return ima_default_measure_policy_setup(str, &init_policy_setup_data); + if (ima_policy) + return 1; + + ima_policy = ORIGINAL_TCB; + return 1; } __setup("ima_tcb", default_measure_policy_setup); +static bool ima_use_appraise_tcb __initdata; +static bool ima_use_appraise_exec_tcb __initdata; +static bool ima_use_appraise_exec_immutable __initdata; +static bool ima_use_secure_boot __initdata; static bool ima_fail_unverifiable_sigs __ro_after_init; /** @@ -263,55 +276,61 @@ static bool ima_fail_unverifiable_sigs __ro_after_init; * @str: string to be parsed * @setup_data: pointer to a structure where parsed data is stored * @fail_unverifiable_sigs: boolean flag treated separately to preserve - * __ro_after_init + * __ro_after_init */ int ima_policy_setup(char *str, struct ima_policy_setup_data *setup_data, bool *fail_unverifiable_sigs) +{ + + /* Currently unused. It will be implemented after namespacing ima + * policy, when global variables are removed. + */ + return 1; +} + +static int __init policy_setup(char *str) { char *p; while ((p = strsep(&str, " |\n")) != NULL) { if (*p == ' ') continue; - if ((strcmp(p, "tcb") == 0) && !setup_data->ima_policy) - setup_data->ima_policy = DEFAULT_TCB; - else if ((strcmp(p, "exec_tcb") == 0) && !setup_data->ima_policy) - setup_data->ima_policy = EXEC_TCB; + if ((strcmp(p, "tcb") == 0) && !ima_policy) + ima_policy = DEFAULT_TCB; + else if ((strcmp(p, "exec_tcb") == 0) && !ima_policy) + ima_policy = EXEC_TCB; else if (strcmp(p, "appraise_tcb") == 0) - setup_data->ima_use_appraise_tcb = true; + ima_use_appraise_tcb = true; else if (strcmp(p, "appraise_exec_tcb") == 0) - setup_data->ima_use_appraise_exec_tcb = true; + ima_use_appraise_exec_tcb = true; else if (strcmp(p, "appraise_exec_immutable") == 0) - setup_data->ima_use_appraise_exec_immutable = true; + ima_use_appraise_exec_immutable = true; else if (strcmp(p, "secure_boot") == 0) - setup_data->ima_use_secure_boot = true; + ima_use_secure_boot = true; else if (strcmp(p, "fail_securely") == 0) - *fail_unverifiable_sigs = true; + ima_fail_unverifiable_sigs = true; else pr_err("policy \"%s\" not found", p); } return 1; } - -static int __init policy_setup(char *str) -{ - return ima_policy_setup(str, &init_policy_setup_data, - &ima_fail_unverifiable_sigs); -} __setup("ima_policy=", policy_setup); int ima_default_appraise_policy_setup(const char *str, struct ima_policy_setup_data *setup_data) { - setup_data->ima_use_appraise_tcb = true; + /* Currently unused. It will be implemented after namespacing ima + * policy, when global variables are removed. + */ return 1; } static int __init default_appraise_policy_setup(char *str) { - return ima_default_appraise_policy_setup(str, &init_policy_setup_data); + ima_use_appraise_tcb = true; + return 1; } __setup("ima_appraise_tcb", default_appraise_policy_setup); @@ -486,11 +505,9 @@ static bool ima_rule_contains_lsm_cond(struct ima_rule_entry *entry) static void ima_lsm_update_rules(void) { struct ima_rule_entry *entry, *e; - struct ima_namespace *ima_ns = get_current_ns(); int result; - list_for_each_entry_safe(entry, e, - &ima_ns->policy_data->ima_policy_rules, list) { + list_for_each_entry_safe(entry, e, &ima_policy_rules, list) { if (!ima_rule_contains_lsm_cond(entry)) continue; @@ -692,13 +709,12 @@ int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid, { struct ima_rule_entry *entry; int action = 0, actmask = flags | (flags << 1); - bool fail_unverifiable_sigs; if (template_desc) *template_desc = ima_template_desc_current(); rcu_read_lock(); - list_for_each_entry_rcu(entry, ima_ns->policy_data->ima_rules, list) { + list_for_each_entry_rcu(entry, ima_rules, list) { if (!(entry->action & actmask)) continue; @@ -713,10 +729,7 @@ int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid, if (entry->action & IMA_APPRAISE) { action |= get_subaction(entry, func); action &= ~IMA_HASH; - fail_unverifiable_sigs = (ima_ns == &init_ima_ns) ? - ima_fail_unverifiable_sigs : - ima_ns->policy_data->ima_fail_unverifiable_sigs; - if (fail_unverifiable_sigs) + if (ima_fail_unverifiable_sigs) action |= IMA_FAIL_UNVERIFIABLE_SIGS; } @@ -751,15 +764,14 @@ void ima_update_policy_flag(struct ima_namespace *ima_ns) { struct ima_rule_entry *entry; - list_for_each_entry(entry, ima_ns->policy_data->ima_rules, list) { + list_for_each_entry(entry, ima_rules, list) { if (entry->action & IMA_DO_MASK) - ima_ns->policy_data->ima_policy_flag |= entry->action; + ima_policy_flag |= entry->action; } - ima_ns->policy_data->ima_appraise |= - (build_ima_appraise | ima_ns->policy_data->temp_ima_appraise); - if (!ima_ns->policy_data->ima_appraise) - ima_ns->policy_data->ima_policy_flag &= ~IMA_APPRAISE; + ima_appraise |= (build_ima_appraise | temp_ima_appraise); + if (!ima_appraise) + ima_policy_flag &= ~IMA_APPRAISE; } static int ima_appraise_flag(enum ima_hooks func) @@ -777,17 +789,16 @@ static int ima_appraise_flag(enum ima_hooks func) return 0; } -static void add_rules(struct ima_namespace *ima_ns, - struct ima_rule_entry *entries, int count, - enum policy_rule_list policy_rule, - const struct ima_policy_setup_data *setup_data) +static void __init add_rules(struct ima_policy_data *policy_data, + struct ima_rule_entry *entries, int count, + enum policy_rule_list policy_rule) { int i = 0; for (i = 0; i < count; i++) { struct ima_rule_entry *entry; - if (setup_data->ima_policy == EXEC_TCB) { + if (ima_policy == EXEC_TCB) { if (entries == dont_measure_rules) if ((entries[i].flags & IMA_FSMAGIC) && entries[i].fsmagic == TMPFS_MAGIC) @@ -799,7 +810,7 @@ static void add_rules(struct ima_namespace *ima_ns, continue; } - if (setup_data->ima_use_appraise_exec_tcb) { + if (ima_use_appraise_exec_tcb) { if (entries == default_appraise_rules) { if (entries[i].action != DONT_APPRAISE) continue; @@ -809,24 +820,14 @@ static void add_rules(struct ima_namespace *ima_ns, } } - if (setup_data->ima_use_appraise_exec_immutable) + if (ima_use_appraise_exec_immutable) if (entries == appraise_exec_rules && (entries[i].flags & IMA_FUNC) && entries[i].func == BPRM_CHECK) entries[i].flags |= IMA_META_IMMUTABLE_REQUIRED; - if (policy_rule & IMA_DEFAULT_POLICY) { - entry = &entries[i]; - if (ima_ns != &init_ima_ns) { - entry = kmemdup(&entries[i], sizeof(*entry), - GFP_KERNEL); - if (!entry) - continue; - } - - list_add_tail(&entry->list, - &ima_ns->policy_data->ima_default_rules); - } + if (policy_rule & IMA_DEFAULT_POLICY) + list_add_tail(&entries[i].list, &ima_default_rules); if (policy_rule & IMA_CUSTOM_POLICY) { entry = kmemdup(&entries[i], sizeof(*entry), @@ -834,12 +835,11 @@ static void add_rules(struct ima_namespace *ima_ns, if (!entry) continue; - list_add_tail(&entry->list, - &ima_ns->policy_data->ima_policy_rules); + list_add_tail(&entry->list, &ima_policy_rules); } if (entries[i].action == APPRAISE) { if (entries != build_appraise_rules) - ima_ns->policy_data->temp_ima_appraise |= + temp_ima_appraise |= ima_appraise_flag(entries[i].func); else build_ima_appraise |= @@ -850,7 +850,7 @@ static void add_rules(struct ima_namespace *ima_ns, static int ima_parse_rule(char *rule, struct ima_rule_entry *entry); -static int ima_init_arch_policy(void) +static int __init ima_init_arch_policy(void) { const char * const *arch_rules; const char * const *rules; @@ -899,71 +899,69 @@ static int ima_init_arch_policy(void) void ima_init_ns_policy(struct ima_namespace *ima_ns, const struct ima_policy_setup_data *setup_data) { - int build_appraise_entries; - - ima_ns->policy_data->ima_appraise = setup_data->ima_appraise; - - if (ima_ns == &init_ima_ns) { - /* - * Based on runtime secure boot flags, insert arch specific - * measurement and appraise rules requiring file signatures for - * both the initial and custom policies, prior to other - * appraise rules. (Highest priority) - */ - arch_entries_size = ima_init_arch_policy(); - if (!arch_entries_size) - pr_info("No architecture policies found\n"); + /* Set policy rules to the empty set of default rules. The rest will be + * implemented after namespacing policy. + */ + ima_ns->policy_data->ima_rules = + &ima_ns->policy_data->ima_default_rules; +} - ima_ns->policy_data->ima_fail_unverifiable_sigs = - ima_fail_unverifiable_sigs; - } +/** + * ima_init_policy - initialize the default measure rules. + * + * ima_rules points to either the ima_default_rules or the + * the new ima_policy_rules. + */ +void __init ima_init_policy(void) +{ + int build_appraise_entries, arch_entries; /* if !ima_policy, we load NO default rules */ - if (setup_data->ima_policy) - add_rules(ima_ns, dont_measure_rules, - ARRAY_SIZE(dont_measure_rules), - IMA_DEFAULT_POLICY, - setup_data); + if (ima_policy) + add_rules(NULL, + dont_measure_rules, ARRAY_SIZE(dont_measure_rules), + IMA_DEFAULT_POLICY); - switch (setup_data->ima_policy) { + switch (ima_policy) { case ORIGINAL_TCB: - add_rules(ima_ns, original_measurement_rules, + add_rules(NULL, original_measurement_rules, ARRAY_SIZE(original_measurement_rules), - IMA_DEFAULT_POLICY, - setup_data); + IMA_DEFAULT_POLICY); break; case EXEC_TCB: fallthrough; case DEFAULT_TCB: - add_rules(ima_ns, default_measurement_rules, + add_rules(NULL, default_measurement_rules, ARRAY_SIZE(default_measurement_rules), - IMA_DEFAULT_POLICY, - setup_data); + IMA_DEFAULT_POLICY); default: break; } - if (setup_data->ima_policy) - add_rules(ima_ns, &ima_parser_measure_rule, 1, IMA_DEFAULT_POLICY, - setup_data); + if (ima_policy) + add_rules(NULL, &ima_parser_measure_rule, 1, IMA_DEFAULT_POLICY); - if (arch_entries_size) - add_rules(ima_ns, - arch_policy_entry, - arch_entries_size, - IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY, - setup_data); + /* + * Based on runtime secure boot flags, insert arch specific measurement + * and appraise rules requiring file signatures for both the initial + * and custom policies, prior to other appraise rules. + * (Highest priority) + */ + arch_entries = ima_init_arch_policy(); + if (!arch_entries) + pr_info("No architecture policies found\n"); + else + add_rules(NULL, arch_policy_entry, arch_entries, + IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY); /* * Insert the builtin "secure_boot" policy rules requiring file * signatures, prior to other appraise rules. */ - if (setup_data->ima_use_secure_boot || - setup_data->ima_use_appraise_exec_tcb) - add_rules(ima_ns, secure_boot_rules, - ARRAY_SIZE(secure_boot_rules), - IMA_DEFAULT_POLICY, - setup_data); + if (ima_use_secure_boot || ima_use_appraise_exec_tcb) + add_rules(NULL, + secure_boot_rules, ARRAY_SIZE(secure_boot_rules), + IMA_DEFAULT_POLICY); /* * Insert the build time appraise rules requiring file signatures @@ -972,53 +970,38 @@ void ima_init_ns_policy(struct ima_namespace *ima_ns, * rules, include either one or the other set of rules, but not both. */ build_appraise_entries = ARRAY_SIZE(build_appraise_rules); - if (build_appraise_entries && (ima_ns == &init_ima_ns)) { - if (setup_data->ima_use_secure_boot) - add_rules(ima_ns, build_appraise_rules, - build_appraise_entries, - IMA_CUSTOM_POLICY, - setup_data); + if (build_appraise_entries) { + if (ima_use_secure_boot) + add_rules(NULL, + build_appraise_rules, build_appraise_entries, + IMA_CUSTOM_POLICY); else - add_rules(ima_ns, build_appraise_rules, - build_appraise_entries, - IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY, - setup_data); + add_rules(NULL, + build_appraise_rules, build_appraise_entries, + IMA_DEFAULT_POLICY | IMA_CUSTOM_POLICY); } - if (setup_data->ima_use_appraise_tcb || - setup_data->ima_use_appraise_exec_tcb) - add_rules(ima_ns, default_appraise_rules, + if (ima_use_appraise_tcb || ima_use_appraise_exec_tcb) + add_rules(NULL, default_appraise_rules, ARRAY_SIZE(default_appraise_rules), - IMA_DEFAULT_POLICY, setup_data); + IMA_DEFAULT_POLICY); - if (setup_data->ima_use_appraise_exec_tcb) - add_rules(ima_ns, appraise_exec_rules, + if (ima_use_appraise_exec_tcb) + add_rules(NULL, appraise_exec_rules, ARRAY_SIZE(appraise_exec_rules), - IMA_DEFAULT_POLICY, setup_data); + IMA_DEFAULT_POLICY); - if (setup_data->ima_use_secure_boot || - setup_data->ima_use_appraise_tcb || - setup_data->ima_use_appraise_exec_tcb) - add_rules(ima_ns, &ima_parser_appraise_rule, 1, - IMA_DEFAULT_POLICY, setup_data); + if (ima_use_secure_boot || ima_use_appraise_tcb || + ima_use_appraise_exec_tcb) + add_rules(NULL, &ima_parser_appraise_rule, 1, IMA_DEFAULT_POLICY); - ima_ns->policy_data->ima_rules = - &ima_ns->policy_data->ima_default_rules; - ima_update_policy_flag(ima_ns); -} - -/** - * ima_init_policy - initialize the default measure rules for the initial ima ns - */ -void __init ima_init_policy(void) -{ - ima_init_ns_policy(&init_ima_ns, &init_policy_setup_data); + ima_update_policy_flag(NULL); } /* Make sure we have a valid policy, at least containing some rules. */ int ima_check_policy(const struct ima_namespace *ima_ns) { - if (list_empty(&ima_ns->policy_data->ima_temp_rules)) + if (list_empty(&ima_temp_rules)) return -EINVAL; return 0; } @@ -1036,18 +1019,14 @@ int ima_check_policy(const struct ima_namespace *ima_ns) */ void ima_update_policy(void) { - /* Update only the current ima namespace */ - struct ima_namespace *ima_ns = get_current_ns(); - struct list_head *policy = &ima_ns->policy_data->ima_policy_rules; + struct list_head *policy = &ima_policy_rules; - list_splice_tail_init_rcu(&ima_ns->policy_data->ima_temp_rules, - policy, synchronize_rcu); + list_splice_tail_init_rcu(&ima_temp_rules, policy, synchronize_rcu); - if (ima_ns->policy_data->ima_rules != policy) { - ima_ns->policy_data->ima_policy_flag = 0; - ima_ns->policy_data->ima_rules = policy; + if (ima_rules != policy) { + ima_policy_flag = 0; + ima_rules = policy; -#ifndef CONFIG_IMA_NS /* * IMA architecture specific policy rules are specified * as strings and converted to an array of ima_entry_rules @@ -1055,9 +1034,8 @@ void ima_update_policy(void) * architecture specific rules stored as an array. */ kfree(arch_policy_entry); -#endif } - ima_update_policy_flag(ima_ns); + ima_update_policy_flag(NULL); /* Custom IMA policy has been loaded */ ima_process_queued_keys(); @@ -1121,7 +1099,6 @@ static int ima_lsm_rule_init(struct ima_rule_entry *entry, substring_t *args, int lsm_rule, int audit_type) { int result; - struct ima_namespace *ima_ns = get_current_ns(); if (entry->lsm[lsm_rule].rule) return -EINVAL; @@ -1138,8 +1115,7 @@ static int ima_lsm_rule_init(struct ima_rule_entry *entry, pr_warn("rule for LSM \'%s\' is undefined\n", entry->lsm[lsm_rule].args_p); - if (ima_ns->policy_data->ima_rules == - &ima_ns->policy_data->ima_default_rules) { + if (ima_rules == &ima_default_rules) { kfree(entry->lsm[lsm_rule].args_p); entry->lsm[lsm_rule].args_p = NULL; result = -EINVAL; @@ -1303,7 +1279,6 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) bool uid_token; struct ima_template_desc *template_desc; int result = 0; - struct ima_namespace *ima_ns = get_current_ns(); ab = integrity_audit_log_start(audit_context(), GFP_KERNEL, AUDIT_INTEGRITY_POLICY_RULE); @@ -1665,8 +1640,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) if (!result && !ima_validate_rule(entry)) result = -EINVAL; else if (entry->action == APPRAISE) - ima_ns->policy_data->temp_ima_appraise |= - ima_appraise_flag(entry->func); + temp_ima_appraise |= ima_appraise_flag(entry->func); if (!result && entry->flags & IMA_MODSIG_ALLOWED) { template_desc = entry->template ? entry->template : @@ -1693,8 +1667,6 @@ ssize_t ima_parse_add_rule(char *rule) struct ima_rule_entry *entry; ssize_t result, len; int audit_info = 0; - /* Add rules only to the current ima namespace */ - struct ima_namespace *ima_ns = get_current_ns(); p = strsep(&rule, "\n"); len = strlen(p) + 1; @@ -1721,7 +1693,7 @@ ssize_t ima_parse_add_rule(char *rule) return result; } - list_add_tail(&entry->list, &ima_ns->policy_data->ima_temp_rules); + list_add_tail(&entry->list, &ima_temp_rules); return len; } @@ -1733,51 +1705,15 @@ ssize_t ima_parse_add_rule(char *rule) * ima_delete_rules() at a time. */ void ima_delete_rules(void) -{ - /* Delete rules only from the current ima namespace */ - struct ima_namespace *ima_ns = get_current_ns(); - struct ima_rule_entry *entry, *tmp; - - ima_ns->policy_data->temp_ima_appraise = 0; - list_for_each_entry_safe(entry, tmp, - &ima_ns->policy_data->ima_temp_rules, list) { - list_del(&entry->list); - ima_free_rule(entry); - } -} - -#ifdef CONFIG_IMA_NS -/** - * ima_delete_ns_rules - delete policy rules and free the memory - * @policy_data: a pointer to the policy data of the given namespace - * @is_root_ns: indicates if the namespace being cleaned up is the root - * namespace - * - * This function should be called only for the inactive namespace, when it is - * being destroyed. - */ -void ima_delete_ns_rules(struct ima_policy_data *policy_data, - bool is_root_ns) { struct ima_rule_entry *entry, *tmp; - /* no locks necessary, namespace is inactive */ - list_for_each_entry_safe(entry, tmp, - &policy_data->ima_policy_rules, list) { + temp_ima_appraise = 0; + list_for_each_entry_safe(entry, tmp, &ima_temp_rules, list) { list_del(&entry->list); ima_free_rule(entry); } - - if (!is_root_ns) { - list_for_each_entry_safe(entry, tmp, - &policy_data->ima_default_rules, - list) { - list_del(&entry->list); - ima_free_rule(entry); - } - } } -#endif #define __ima_hook_stringify(func, str) (#func), @@ -1801,10 +1737,9 @@ void *ima_policy_start(struct seq_file *m, loff_t *pos) { loff_t l = *pos; struct ima_rule_entry *entry; - struct ima_namespace *ima_ns = get_current_ns(); rcu_read_lock(); - list_for_each_entry_rcu(entry, ima_ns->policy_data->ima_rules, list) { + list_for_each_entry_rcu(entry, ima_rules, list) { if (!l--) { rcu_read_unlock(); return entry; @@ -1816,7 +1751,6 @@ void *ima_policy_start(struct seq_file *m, loff_t *pos) void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos) { - struct ima_namespace *ima_ns = get_current_ns(); struct ima_rule_entry *entry = v; rcu_read_lock(); @@ -1824,7 +1758,7 @@ void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos) rcu_read_unlock(); (*pos)++; - return (&entry->list == ima_ns->policy_data->ima_rules) ? NULL : entry; + return (&entry->list == ima_rules) ? NULL : entry; } void ima_policy_stop(struct seq_file *m, void *v) @@ -2022,7 +1956,6 @@ int ima_policy_show(struct seq_file *m, void *v) */ bool ima_appraise_signature(enum kernel_read_file_id id) { - struct ima_namespace *ima_ns = get_current_ns(); struct ima_rule_entry *entry; bool found = false; enum ima_hooks func; @@ -2033,7 +1966,7 @@ bool ima_appraise_signature(enum kernel_read_file_id id) func = read_idmap[id] ?: FILE_CHECK; rcu_read_lock(); - list_for_each_entry_rcu(entry, ima_ns->policy_data->ima_rules, list) { + list_for_each_entry_rcu(entry, ima_rules, list) { if (entry->action != APPRAISE) continue; diff --git a/security/integrity/ima/ima_queue_keys.c b/security/integrity/ima/ima_queue_keys.c index 542cbe894a99..34ca54ba52b7 100644 --- a/security/integrity/ima/ima_queue_keys.c +++ b/security/integrity/ima/ima_queue_keys.c @@ -110,11 +110,8 @@ bool ima_queue_key(struct key *keyring, const void *payload, if (!entry) return false; - /* Queued keys will be processed according to the root IMA namespace - * policy, therefore allow queueing only for the root namespace. - */ mutex_lock(&ima_keys_lock); - if (!ima_process_keys && (get_current_ns() == &init_ima_ns)) { + if (!ima_process_keys) { list_add_tail(&entry->list, &ima_keys); queued = true; } @@ -161,15 +158,12 @@ void ima_process_queued_keys(void) list_for_each_entry_safe(entry, tmp, &ima_keys, list) { if (!timer_expired) - /* Queued keys are always measured according to the - * initial namespace policy. - */ process_buffer_measurement(NULL, entry->payload, entry->payload_len, entry->keyring_name, KEY_CHECK, 0, entry->keyring_name, - &init_ima_ns); + NULL); list_del(&entry->list); ima_free_key_entry(entry); } diff --git a/security/security.c b/security/security.c index 33d0d1a28b42..4fb58543eeb9 100644 --- a/security/security.c +++ b/security/security.c @@ -990,7 +990,7 @@ static void inode_free_by_rcu(struct rcu_head *head) void security_inode_free(struct inode *inode) { - ima_inode_free(inode); + integrity_inode_free(inode); call_void_hook(inode_free_security, inode); /* * The inode may still be referenced in a path walk and -- 2.20.1