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 Jianfengxiujianfeng@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