提交 27229fcf 编写于 作者: K Krzysztof Struczynski 提交者: Zheng Zengkai

ima: Enable per ima namespace policy settings

hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I49KW1
CVE: NA

--------------------------------

Set ima policy per namespace and remove the global settings. Operations
on the objects may now have impact in more than one ima namespace and
therefore iterate all active ima namespaces when necessary.

Read-write violations can now happen across namespaces and should be
checked in all namespaces for each relevant ima hook.

Inform all concerned ima namespaces about the actions on the objects
when the object is freed. E.g. if an object had been appraised in the
ima_ns_1 and then modified in the ima_ns_2, appraised flag in the
ima_ns_1 is cleared and the object will be re-appraised in the ima_ns_1
namespace.
Signed-off-by: NKrzysztof Struczynski <krzysztof.struczynski@huawei.com>
Reviewed-by: NZhang Tianxing <zhangtianxing3@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 5f7f33c2
...@@ -37,6 +37,8 @@ extern int ima_post_read_file(struct file *file, void *buf, loff_t size, ...@@ -37,6 +37,8 @@ extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
extern void ima_post_path_mknod(struct dentry *dentry); extern void ima_post_path_mknod(struct dentry *dentry);
extern int ima_file_hash(struct file *file, char *buf, size_t buf_size); 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_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 #ifdef CONFIG_IMA_KEXEC
extern void ima_add_kexec_buffer(struct kimage *image); extern void ima_add_kexec_buffer(struct kimage *image);
...@@ -128,6 +130,15 @@ static inline int ima_file_hash(struct file *file, char *buf, size_t buf_size) ...@@ -128,6 +130,15 @@ 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_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 */ #endif /* CONFIG_IMA */
#ifndef CONFIG_IMA_KEXEC #ifndef CONFIG_IMA_KEXEC
......
...@@ -362,6 +362,13 @@ SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd, ...@@ -362,6 +362,13 @@ SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd,
if (!capable(CAP_SYS_BOOT) || kexec_load_disabled) if (!capable(CAP_SYS_BOOT) || kexec_load_disabled)
return -EPERM; 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 */ /* Make sure we have a legal set of flags */
if (flags != (flags & KEXEC_FILE_FLAGS)) if (flags != (flags & KEXEC_FILE_FLAGS))
return -EINVAL; return -EINVAL;
......
...@@ -44,15 +44,11 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10 }; ...@@ -44,15 +44,11 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8, TPM_PCR10 = 10 };
#define NR_BANKS(chip) ((chip != NULL) ? chip->nr_allocated_banks : 0) #define NR_BANKS(chip) ((chip != NULL) ? chip->nr_allocated_banks : 0)
/* current content of the policy */
extern int ima_policy_flag;
/* set during initialization */ /* set during initialization */
extern int ima_hash_algo; extern int ima_hash_algo;
extern int ima_sha1_idx __ro_after_init; extern int ima_sha1_idx __ro_after_init;
extern int ima_hash_algo_idx __ro_after_init; extern int ima_hash_algo_idx __ro_after_init;
extern int ima_extra_slots __ro_after_init; extern int ima_extra_slots __ro_after_init;
extern int ima_appraise;
extern struct tpm_chip *ima_tpm_chip; extern struct tpm_chip *ima_tpm_chip;
extern int ima_digest_list_pcr; extern int ima_digest_list_pcr;
extern bool ima_plus_standard_pcr; extern bool ima_plus_standard_pcr;
...@@ -69,6 +65,8 @@ struct ima_policy_setup_data { ...@@ -69,6 +65,8 @@ struct ima_policy_setup_data {
int ima_appraise; int ima_appraise;
bool ima_use_secure_boot; bool ima_use_secure_boot;
bool ima_use_appraise_tcb; bool ima_use_appraise_tcb;
bool ima_use_appraise_exec_tcb;
bool ima_use_appraise_exec_immutable;
}; };
/* IMA event related data */ /* IMA event related data */
...@@ -402,6 +400,9 @@ struct ima_policy_data { ...@@ -402,6 +400,9 @@ struct ima_policy_data {
int temp_ima_appraise; 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_data init_policy_data;
extern struct ima_policy_setup_data init_policy_setup_data; extern struct ima_policy_setup_data init_policy_setup_data;
...@@ -415,6 +416,9 @@ static inline struct ima_namespace *get_current_ns(void) ...@@ -415,6 +416,9 @@ static inline struct ima_namespace *get_current_ns(void)
{ {
return current->nsproxy->ima_ns; return current->nsproxy->ima_ns;
} }
void ima_delete_ns_rules(struct ima_policy_data *policy_data,
bool is_root_ns);
#else #else
static inline int __init ima_init_namespace(void) static inline int __init ima_init_namespace(void)
{ {
......
...@@ -212,7 +212,7 @@ int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid, ...@@ -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; int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE | IMA_HASH;
flags &= ima_policy_flag; flags &= ima_ns->policy_data->ima_policy_flag;
return ima_match_policy(inode, cred, secid, func, mask, flags, pcr, return ima_match_policy(inode, cred, secid, func, mask, flags, pcr,
template_desc, keyring, ima_ns); template_desc, keyring, ima_ns);
......
...@@ -21,18 +21,10 @@ static bool ima_appraise_req_evm __ro_after_init; ...@@ -21,18 +21,10 @@ static bool ima_appraise_req_evm __ro_after_init;
int ima_default_appraise_setup(const char *str, int ima_default_appraise_setup(const char *str,
struct ima_policy_setup_data *setup_data) 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 #ifdef CONFIG_IMA_APPRAISE_BOOTPARAM
bool sb_state = arch_ima_get_secureboot(); bool sb_state = arch_ima_get_secureboot();
int appraisal_state = ima_appraise; int appraisal_state = setup_data->ima_appraise;
if (strncmp(str, "off", 3) == 0) if (strncmp(str, "off", 3) == 0)
appraisal_state = 0; appraisal_state = 0;
...@@ -52,7 +44,7 @@ static int __init default_appraise_setup(char *str) ...@@ -52,7 +44,7 @@ static int __init default_appraise_setup(char *str)
pr_info("Secure boot enabled: ignoring ima_appraise=%s option", pr_info("Secure boot enabled: ignoring ima_appraise=%s option",
str); str);
} else { } else {
ima_appraise = appraisal_state; setup_data->ima_appraise = appraisal_state;
} }
#endif #endif
if (strcmp(str, "enforce-evm") == 0 || if (strcmp(str, "enforce-evm") == 0 ||
...@@ -61,6 +53,11 @@ static int __init default_appraise_setup(char *str) ...@@ -61,6 +53,11 @@ static int __init default_appraise_setup(char *str)
return 1; 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); __setup("ima_appraise=", default_appraise_setup);
static bool ima_appraise_no_metadata __ro_after_init; static bool ima_appraise_no_metadata __ro_after_init;
...@@ -87,7 +84,10 @@ __setup("ima_appraise_digest_list=", appraise_digest_list_setup); ...@@ -87,7 +84,10 @@ __setup("ima_appraise_digest_list=", appraise_digest_list_setup);
*/ */
bool is_ima_appraise_enabled(const struct ima_namespace *ima_ns) bool is_ima_appraise_enabled(const struct ima_namespace *ima_ns)
{ {
return ima_appraise & IMA_APPRAISE_ENFORCE; if (!ima_ns)
return false;
return ima_ns->policy_data->ima_appraise & IMA_APPRAISE_ENFORCE;
} }
/* /*
...@@ -95,18 +95,18 @@ bool is_ima_appraise_enabled(const struct ima_namespace *ima_ns) ...@@ -95,18 +95,18 @@ bool is_ima_appraise_enabled(const struct ima_namespace *ima_ns)
* *
* Return 1 to appraise or hash * Return 1 to appraise or hash
*/ */
int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func, int ima_must_appraise(struct inode *inode, int mask,
struct ima_namespace *ima_ns) enum ima_hooks func, struct ima_namespace *ima_ns)
{ {
u32 secid; u32 secid;
if (!ima_appraise) if (!ima_ns->policy_data->ima_appraise)
return 0; return 0;
security_task_getsecid(current, &secid); security_task_getsecid(current, &secid);
return ima_match_policy(inode, current_cred(), secid, func, mask, return ima_match_policy(inode, current_cred(), secid, func, mask,
IMA_APPRAISE | IMA_HASH, NULL, NULL, NULL, IMA_APPRAISE | IMA_HASH, NULL, NULL, NULL,
NULL); ima_ns);
} }
static int ima_fix_xattr(struct dentry *dentry, static int ima_fix_xattr(struct dentry *dentry,
...@@ -352,7 +352,7 @@ int ima_check_blacklist(struct integrity_iint_cache *iint, ...@@ -352,7 +352,7 @@ int ima_check_blacklist(struct integrity_iint_cache *iint,
if ((rc == -EPERM) && (iint->flags & IMA_MEASURE)) if ((rc == -EPERM) && (iint->flags & IMA_MEASURE))
process_buffer_measurement(NULL, digest, digestsize, process_buffer_measurement(NULL, digest, digestsize,
"blacklisted-hash", NONE, "blacklisted-hash", NONE,
pcr, NULL, NULL); pcr, NULL, ima_ns);
} }
return rc; return rc;
...@@ -381,6 +381,7 @@ int ima_appraise_measurement(enum ima_hooks func, ...@@ -381,6 +381,7 @@ int ima_appraise_measurement(enum ima_hooks func,
int rc = xattr_len, rc_evm; int rc = xattr_len, rc_evm;
char _buf[sizeof(struct evm_ima_xattr_data) + 1 + SHA512_DIGEST_SIZE]; char _buf[sizeof(struct evm_ima_xattr_data) + 1 + SHA512_DIGEST_SIZE];
bool try_modsig = iint->flags & IMA_MODSIG_ALLOWED && modsig; 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 not appraising a modsig, we need an xattr. */
if (!(inode->i_opflags & IOP_XATTR) && !try_modsig) if (!(inode->i_opflags & IOP_XATTR) && !try_modsig)
...@@ -509,7 +510,8 @@ int ima_appraise_measurement(enum ima_hooks func, ...@@ -509,7 +510,8 @@ int ima_appraise_measurement(enum ima_hooks func,
op, cause, rc, 0); op, cause, rc, 0);
} else if (status != INTEGRITY_PASS) { } else if (status != INTEGRITY_PASS) {
/* Fix mode, but don't replace file signatures. */ /* Fix mode, but don't replace file signatures. */
if ((ima_appraise & IMA_APPRAISE_FIX) && !try_modsig && if ((ima_ns->policy_data->ima_appraise & IMA_APPRAISE_FIX) &&
!try_modsig &&
(!xattr_value || (!xattr_value ||
xattr_value->type != EVM_IMA_XATTR_DIGSIG)) { xattr_value->type != EVM_IMA_XATTR_DIGSIG)) {
if (!ima_fix_xattr(dentry, iint)) if (!ima_fix_xattr(dentry, iint))
...@@ -574,18 +576,30 @@ void ima_inode_post_setattr(struct dentry *dentry) ...@@ -574,18 +576,30 @@ void ima_inode_post_setattr(struct dentry *dentry)
struct inode *inode = d_backing_inode(dentry); struct inode *inode = d_backing_inode(dentry);
struct integrity_iint_cache *iint; struct integrity_iint_cache *iint;
int action; int action;
struct ima_namespace *ima_ns;
if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode) if (!S_ISREG(inode->i_mode) ||
|| !(inode->i_opflags & IOP_XATTR)) !(inode->i_opflags & IOP_XATTR))
return; return;
action = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR, NULL); down_read(&ima_ns_list_lock);
iint = integrity_iint_find(inode); 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) { if (iint) {
set_bit(IMA_CHANGE_ATTR, &iint->atomic_flags); set_bit(IMA_CHANGE_ATTR, &iint->atomic_flags);
if (!action) if (!action)
clear_bit(IMA_UPDATE_XATTR, &iint->atomic_flags); clear_bit(IMA_UPDATE_XATTR,
&iint->atomic_flags);
}
} }
up_read(&ima_ns_list_lock);
} }
/* /*
...@@ -607,19 +621,30 @@ static int ima_protect_xattr(struct dentry *dentry, const char *xattr_name, ...@@ -607,19 +621,30 @@ static int ima_protect_xattr(struct dentry *dentry, const char *xattr_name,
static void ima_reset_appraise_flags(struct inode *inode, int digsig) static void ima_reset_appraise_flags(struct inode *inode, int digsig)
{ {
struct integrity_iint_cache *iint; struct integrity_iint_cache *iint;
struct ima_namespace *ima_ns;
if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)) if (!S_ISREG(inode->i_mode))
return; return;
iint = integrity_iint_find(inode); 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) if (!iint)
return; continue;
iint->measured_pcrs = 0; iint->measured_pcrs = 0;
set_bit(IMA_CHANGE_XATTR, &iint->atomic_flags); set_bit(IMA_CHANGE_XATTR, &iint->atomic_flags);
if (digsig) if (digsig)
set_bit(IMA_DIGSIG, &iint->atomic_flags); set_bit(IMA_DIGSIG, &iint->atomic_flags);
else else
clear_bit(IMA_DIGSIG, &iint->atomic_flags); clear_bit(IMA_DIGSIG, &iint->atomic_flags);
}
up_read(&ima_ns_list_lock);
} }
int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
......
...@@ -29,6 +29,16 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key, ...@@ -29,6 +29,16 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key,
unsigned long flags, bool create) unsigned long flags, bool create)
{ {
bool queued = false; 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. */ /* Only asymmetric keys are handled by this hook. */
if (key->type != &key_type_asymmetric) if (key->type != &key_type_asymmetric)
...@@ -60,6 +70,5 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key, ...@@ -60,6 +70,5 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key,
*/ */
process_buffer_measurement(NULL, payload, payload_len, process_buffer_measurement(NULL, payload, payload_len,
keyring->description, KEY_CHECK, 0, keyring->description, KEY_CHECK, 0,
keyring->description, keyring->description, ima_ns);
NULL);
} }
...@@ -167,7 +167,7 @@ int ima_parse_compact_list(loff_t size, void *buf, int op) ...@@ -167,7 +167,7 @@ int ima_parse_compact_list(loff_t size, void *buf, int op)
size_t digest_len; size_t digest_len;
int ret = 0, i; int ret = 0, i;
if (!(ima_digest_list_actions & ima_policy_flag)) if (!(ima_digest_list_actions & init_policy_data.ima_policy_flag))
return -EACCES; return -EACCES;
while (bufp < bufendp) { while (bufp < bufendp) {
...@@ -383,7 +383,7 @@ void __init ima_load_digest_lists(void) ...@@ -383,7 +383,7 @@ void __init ima_load_digest_lists(void)
.ctx.actor = load_digest_list, .ctx.actor = load_digest_list,
}; };
if (!(ima_digest_list_actions & ima_policy_flag)) if (!(ima_digest_list_actions & init_policy_data.ima_policy_flag))
return; return;
ret = kern_path(CONFIG_IMA_DIGEST_LISTS_DIR, 0, &path); ret = kern_path(CONFIG_IMA_DIGEST_LISTS_DIR, 0, &path);
......
...@@ -365,6 +365,7 @@ static ssize_t ima_write_data(struct file *file, const char __user *buf, ...@@ -365,6 +365,7 @@ static ssize_t ima_write_data(struct file *file, const char __user *buf,
ssize_t result; ssize_t result;
struct dentry *dentry = file_dentry(file); struct dentry *dentry = file_dentry(file);
int i; int i;
struct ima_namespace *ima_ns = get_current_ns();
/* No partial writes. */ /* No partial writes. */
result = -EINVAL; result = -EINVAL;
...@@ -400,7 +401,7 @@ static ssize_t ima_write_data(struct file *file, const char __user *buf, ...@@ -400,7 +401,7 @@ static ssize_t ima_write_data(struct file *file, const char __user *buf,
if (data[0] == '/') { if (data[0] == '/') {
result = ima_read_sfs_file(data, dentry); result = ima_read_sfs_file(data, dentry);
} else if (dentry == ima_policy) { } else if (dentry == ima_policy) {
if (ima_appraise & IMA_APPRAISE_POLICY) { if (ima_ns->policy_data->ima_appraise & IMA_APPRAISE_POLICY) {
pr_err("signed policy file (specified " pr_err("signed policy file (specified "
"as an absolute pathname) required\n"); "as an absolute pathname) required\n");
integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL, integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL,
...@@ -515,6 +516,7 @@ static int ima_release_data_upload(struct inode *inode, struct file *file) ...@@ -515,6 +516,7 @@ static int ima_release_data_upload(struct inode *inode, struct file *file)
struct dentry *dentry = file_dentry(file); struct dentry *dentry = file_dentry(file);
const char *cause = valid_policy ? "completed" : "failed"; const char *cause = valid_policy ? "completed" : "failed";
enum ima_fs_flags flag = ima_get_dentry_flag(dentry); 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) if ((file->f_flags & O_ACCMODE) == O_RDONLY)
return seq_release(inode, file); return seq_release(inode, file);
...@@ -527,7 +529,7 @@ static int ima_release_data_upload(struct inode *inode, struct file *file) ...@@ -527,7 +529,7 @@ static int ima_release_data_upload(struct inode *inode, struct file *file)
return 0; return 0;
} }
if (valid_policy && ima_check_policy(NULL) < 0) { if (valid_policy && ima_check_policy(ima_ns) < 0) {
cause = "failed"; cause = "failed";
valid_policy = 0; valid_policy = 0;
} }
......
...@@ -118,15 +118,16 @@ static int __init ima_add_boot_aggregate(void) ...@@ -118,15 +118,16 @@ static int __init ima_add_boot_aggregate(void)
#ifdef CONFIG_IMA_LOAD_X509 #ifdef CONFIG_IMA_LOAD_X509
void __init ima_load_x509(void) void __init ima_load_x509(void)
{ {
int unset_flags = ima_policy_flag & IMA_APPRAISE; int unset_flags =
init_ima_ns.policy_data->ima_policy_flag & IMA_APPRAISE;
ima_policy_flag &= ~unset_flags; init_ima_ns.policy_data->ima_policy_flag &= ~unset_flags;
integrity_load_x509(INTEGRITY_KEYRING_IMA, CONFIG_IMA_X509_PATH); integrity_load_x509(INTEGRITY_KEYRING_IMA, CONFIG_IMA_X509_PATH);
/* load also EVM key to avoid appraisal */ /* load also EVM key to avoid appraisal */
evm_load_x509(); evm_load_x509();
ima_policy_flag |= unset_flags; init_ima_ns.policy_data->ima_policy_flag |= unset_flags;
} }
#endif #endif
......
...@@ -30,12 +30,6 @@ ...@@ -30,12 +30,6 @@
#include "ima.h" #include "ima.h"
#include "ima_digest_list.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; int ima_hash_algo = HASH_ALGO_SHA1;
/* Actions (measure/appraisal) for which digest lists can be used */ /* Actions (measure/appraisal) for which digest lists can be used */
...@@ -134,7 +128,8 @@ static void ima_rdwr_violation_check(struct file *file, ...@@ -134,7 +128,8 @@ static void ima_rdwr_violation_check(struct file *file,
if (mode & FMODE_WRITE) { if (mode & FMODE_WRITE) {
if (atomic_read(&inode->i_readcount) && IS_IMA(inode)) { if (atomic_read(&inode->i_readcount) && IS_IMA(inode)) {
if (!iint) if (!iint)
iint = integrity_iint_find(inode); iint = integrity_iint_rb_find(ima_ns->iint_tree,
inode);
/* IMA_MEASURE is set from reader side */ /* IMA_MEASURE is set from reader side */
if (iint && test_bit(IMA_MUST_MEASURE, if (iint && test_bit(IMA_MUST_MEASURE,
&iint->atomic_flags)) &iint->atomic_flags))
...@@ -214,11 +209,38 @@ static int ima_read_xattr(struct dentry *dentry, ...@@ -214,11 +209,38 @@ static int ima_read_xattr(struct dentry *dentry,
return ret; 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, static void ima_check_last_writer(struct integrity_iint_cache *iint,
struct inode *inode, struct file *file) struct inode *inode, struct file *file)
{ {
fmode_t mode = file->f_mode; fmode_t mode = file->f_mode;
bool update; bool update;
struct ima_namespace *ima_ns = (struct ima_namespace *)file->f_ima;
if (!(mode & FMODE_WRITE)) if (!(mode & FMODE_WRITE))
return; return;
...@@ -232,6 +254,9 @@ static void ima_check_last_writer(struct integrity_iint_cache *iint, ...@@ -232,6 +254,9 @@ static void ima_check_last_writer(struct integrity_iint_cache *iint,
(iint->flags & IMA_NEW_FILE)) { (iint->flags & IMA_NEW_FILE)) {
iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE); iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE);
iint->measured_pcrs = 0; iint->measured_pcrs = 0;
ima_check_active_ns(ima_ns, inode);
if (update) if (update)
ima_update_xattr(iint, file); ima_update_xattr(iint, file);
} }
...@@ -281,10 +306,10 @@ void ima_file_free(struct file *file) ...@@ -281,10 +306,10 @@ void ima_file_free(struct file *file)
if (unlikely(!(file->f_mode & FMODE_OPENED))) if (unlikely(!(file->f_mode & FMODE_OPENED)))
goto out; goto out;
if (!ima_policy_flag || !S_ISREG(inode->i_mode)) if (!ima_ns->policy_data->ima_policy_flag || !S_ISREG(inode->i_mode))
goto out; goto out;
iint = integrity_iint_find(inode); iint = integrity_iint_rb_find(ima_ns->iint_tree, inode);
if (!iint) if (!iint)
goto out; goto out;
...@@ -293,7 +318,7 @@ void ima_file_free(struct file *file) ...@@ -293,7 +318,7 @@ void ima_file_free(struct file *file)
put_ima_ns(ima_ns); put_ima_ns(ima_ns);
} }
static int process_measurement(struct file *file, const struct cred *cred, static int process_ns_measurement(struct file *file, const struct cred *cred,
u32 secid, char *buf, loff_t size, int mask, u32 secid, char *buf, loff_t size, int mask,
enum ima_hooks func, enum ima_hooks func,
struct ima_namespace *ima_ns) struct ima_namespace *ima_ns)
...@@ -312,8 +337,9 @@ static int process_measurement(struct file *file, const struct cred *cred, ...@@ -312,8 +337,9 @@ static int process_measurement(struct file *file, const struct cred *cred,
int xattr_len = 0; int xattr_len = 0;
bool violation_check; bool violation_check;
enum hash_algo hash_algo; enum hash_algo hash_algo;
struct ima_namespace *current_ima_ns = get_current_ns();
if (!ima_policy_flag || !S_ISREG(inode->i_mode)) if (!ima_ns->policy_data->ima_policy_flag)
return 0; return 0;
/* Return an IMA_MEASURE, IMA_APPRAISE, IMA_AUDIT action /* Return an IMA_MEASURE, IMA_APPRAISE, IMA_AUDIT action
...@@ -323,7 +349,8 @@ static int process_measurement(struct file *file, const struct cred *cred, ...@@ -323,7 +349,8 @@ static int process_measurement(struct file *file, const struct cred *cred,
action = ima_get_action(inode, cred, secid, mask, func, &pcr, action = ima_get_action(inode, cred, secid, mask, func, &pcr,
&template_desc, NULL, ima_ns); &template_desc, NULL, ima_ns);
violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) && violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) &&
(ima_policy_flag & IMA_MEASURE)); (ima_ns->policy_data->ima_policy_flag &
IMA_MEASURE));
if (!action && !violation_check) if (!action && !violation_check)
return 0; return 0;
...@@ -336,7 +363,7 @@ static int process_measurement(struct file *file, const struct cred *cred, ...@@ -336,7 +363,7 @@ static int process_measurement(struct file *file, const struct cred *cred,
inode_lock(inode); inode_lock(inode);
if (action) { if (action) {
iint = integrity_inode_get(inode); iint = integrity_inode_rb_get(ima_ns->iint_tree, inode);
if (!iint) if (!iint)
rc = -ENOMEM; rc = -ENOMEM;
} }
...@@ -351,6 +378,8 @@ static int process_measurement(struct file *file, const struct cred *cred, ...@@ -351,6 +378,8 @@ static int process_measurement(struct file *file, const struct cred *cred,
goto out; goto out;
if (!action) if (!action)
goto out; goto out;
if (ima_ns != current_ima_ns)
goto out;
mutex_lock(&iint->mutex); mutex_lock(&iint->mutex);
...@@ -478,7 +507,8 @@ static int process_measurement(struct file *file, const struct cred *cred, ...@@ -478,7 +507,8 @@ static int process_measurement(struct file *file, const struct cred *cred,
if (pathbuf) if (pathbuf)
__putname(pathbuf); __putname(pathbuf);
if (must_appraise) { if (must_appraise) {
if (rc && (ima_appraise & IMA_APPRAISE_ENFORCE)) if (rc &&
(ima_ns->policy_data->ima_appraise & IMA_APPRAISE_ENFORCE))
return -EACCES; return -EACCES;
if (file->f_mode & FMODE_WRITE) if (file->f_mode & FMODE_WRITE)
set_bit(IMA_UPDATE_XATTR, &iint->atomic_flags); set_bit(IMA_UPDATE_XATTR, &iint->atomic_flags);
...@@ -486,6 +516,32 @@ static int process_measurement(struct file *file, const struct cred *cred, ...@@ -486,6 +516,32 @@ static int process_measurement(struct file *file, const struct cred *cred,
return 0; 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. * ima_file_mmap - based on policy, collect/store measurement.
* @file: pointer to the file to be measured (May be NULL) * @file: pointer to the file to be measured (May be NULL)
...@@ -504,7 +560,7 @@ int ima_file_mmap(struct file *file, unsigned long prot) ...@@ -504,7 +560,7 @@ int ima_file_mmap(struct file *file, unsigned long prot)
if (file && (prot & PROT_EXEC)) { if (file && (prot & PROT_EXEC)) {
security_task_getsecid(current, &secid); security_task_getsecid(current, &secid);
return process_measurement(file, current_cred(), secid, NULL, return process_measurement(file, current_cred(), secid, NULL,
0, MAY_EXEC, MMAP_CHECK, NULL); 0, MAY_EXEC, MMAP_CHECK);
} }
return 0; return 0;
...@@ -524,6 +580,7 @@ int ima_file_mmap(struct file *file, unsigned long prot) ...@@ -524,6 +580,7 @@ int ima_file_mmap(struct file *file, unsigned long prot)
*/ */
int ima_file_mprotect(struct vm_area_struct *vma, 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 ima_template_desc *template;
struct file *file = vma->vm_file; struct file *file = vma->vm_file;
char filename[NAME_MAX]; char filename[NAME_MAX];
...@@ -536,14 +593,15 @@ int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot) ...@@ -536,14 +593,15 @@ int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot)
int pcr; int pcr;
/* Is mprotect making an mmap'ed file executable? */ /* Is mprotect making an mmap'ed file executable? */
if (!(ima_policy_flag & IMA_APPRAISE) || !vma->vm_file || if (!(ima_ns->policy_data->ima_policy_flag & IMA_APPRAISE) ||
!(prot & PROT_EXEC) || (vma->vm_flags & VM_EXEC)) !vma->vm_file || !(prot & PROT_EXEC) ||
(vma->vm_flags & VM_EXEC))
return 0; return 0;
security_task_getsecid(current, &secid); security_task_getsecid(current, &secid);
inode = file_inode(vma->vm_file); inode = file_inode(vma->vm_file);
action = ima_get_action(inode, current_cred(), secid, MAY_EXEC, action = ima_get_action(inode, current_cred(), secid, MAY_EXEC,
MMAP_CHECK, &pcr, &template, 0, NULL); MMAP_CHECK, &pcr, &template, 0, ima_ns);
/* Is the mmap'ed file in policy? */ /* Is the mmap'ed file in policy? */
if (!(action & (IMA_MEASURE | IMA_APPRAISE_SUBMASK))) if (!(action & (IMA_MEASURE | IMA_APPRAISE_SUBMASK)))
...@@ -582,13 +640,13 @@ int ima_bprm_check(struct linux_binprm *bprm) ...@@ -582,13 +640,13 @@ int ima_bprm_check(struct linux_binprm *bprm)
security_task_getsecid(current, &secid); security_task_getsecid(current, &secid);
ret = process_measurement(bprm->file, current_cred(), secid, NULL, 0, ret = process_measurement(bprm->file, current_cred(), secid, NULL, 0,
MAY_EXEC, BPRM_CHECK, NULL); MAY_EXEC, BPRM_CHECK);
if (ret) if (ret)
return ret; return ret;
security_cred_getsecid(bprm->cred, &secid); security_cred_getsecid(bprm->cred, &secid);
return process_measurement(bprm->file, bprm->cred, secid, NULL, 0, return process_measurement(bprm->file, bprm->cred, secid, NULL, 0,
MAY_EXEC, CREDS_CHECK, NULL); MAY_EXEC, CREDS_CHECK);
} }
/** /**
...@@ -609,7 +667,7 @@ int ima_file_check(struct file *file, int mask) ...@@ -609,7 +667,7 @@ int ima_file_check(struct file *file, int mask)
security_task_getsecid(current, &secid); security_task_getsecid(current, &secid);
rc = process_measurement(file, current_cred(), secid, NULL, 0, rc = process_measurement(file, current_cred(), secid, NULL, 0,
mask & (MAY_READ | MAY_WRITE | MAY_EXEC | mask & (MAY_READ | MAY_WRITE | MAY_EXEC |
MAY_APPEND), FILE_CHECK, NULL); MAY_APPEND), FILE_CHECK);
if (ima_current_is_parser() && !rc) if (ima_current_is_parser() && !rc)
ima_check_measured_appraised(file); ima_check_measured_appraised(file);
return rc; return rc;
...@@ -618,7 +676,7 @@ EXPORT_SYMBOL_GPL(ima_file_check); ...@@ -618,7 +676,7 @@ EXPORT_SYMBOL_GPL(ima_file_check);
/** /**
* ima_file_hash - return the stored measurement if a file has been hashed and * ima_file_hash - return the stored measurement if a file has been hashed and
* is in the iint cache. * is in the iint cache of the current IMA namespace.
* @file: pointer to the file * @file: pointer to the file
* @buf: buffer in which to store the hash * @buf: buffer in which to store the hash
* @buf_size: length of the buffer * @buf_size: length of the buffer
...@@ -636,6 +694,7 @@ EXPORT_SYMBOL_GPL(ima_file_check); ...@@ -636,6 +694,7 @@ EXPORT_SYMBOL_GPL(ima_file_check);
*/ */
int ima_file_hash(struct file *file, char *buf, size_t buf_size) 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 inode *inode;
struct integrity_iint_cache *iint; struct integrity_iint_cache *iint;
int hash_algo; int hash_algo;
...@@ -643,11 +702,11 @@ int ima_file_hash(struct file *file, char *buf, size_t buf_size) ...@@ -643,11 +702,11 @@ int ima_file_hash(struct file *file, char *buf, size_t buf_size)
if (!file) if (!file)
return -EINVAL; return -EINVAL;
if (!ima_policy_flag) if (!ima_ns->policy_data->ima_policy_flag)
return -EOPNOTSUPP; return -EOPNOTSUPP;
inode = file_inode(file); inode = file_inode(file);
iint = integrity_iint_find(inode); iint = integrity_iint_rb_find(ima_ns->iint_tree, inode);
if (!iint) if (!iint)
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -685,21 +744,30 @@ EXPORT_SYMBOL_GPL(ima_file_hash); ...@@ -685,21 +744,30 @@ EXPORT_SYMBOL_GPL(ima_file_hash);
*/ */
void ima_post_create_tmpfile(struct inode *inode) void ima_post_create_tmpfile(struct inode *inode)
{ {
struct ima_namespace *ima_ns;
struct integrity_iint_cache *iint; struct integrity_iint_cache *iint;
int must_appraise; int must_appraise;
must_appraise = ima_must_appraise(inode, MAY_ACCESS, FILE_CHECK, NULL); 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) if (!must_appraise)
return; continue;
/* Nothing to do if we can't allocate memory */ /* Nothing to do if we can't allocate memory */
iint = integrity_inode_get(inode); iint = integrity_inode_rb_get(ima_ns->iint_tree, inode);
if (!iint) if (!iint)
return; continue;
/* needed for writing the security xattrs */ /* needed for writing the security xattrs */
set_bit(IMA_UPDATE_XATTR, &iint->atomic_flags); set_bit(IMA_UPDATE_XATTR, &iint->atomic_flags);
iint->ima_file_status = INTEGRITY_PASS; iint->ima_file_status = INTEGRITY_PASS;
}
up_read(&ima_ns_list_lock);
} }
/** /**
...@@ -711,21 +779,30 @@ void ima_post_create_tmpfile(struct inode *inode) ...@@ -711,21 +779,30 @@ void ima_post_create_tmpfile(struct inode *inode)
*/ */
void ima_post_path_mknod(struct dentry *dentry) void ima_post_path_mknod(struct dentry *dentry)
{ {
struct ima_namespace *ima_ns;
struct integrity_iint_cache *iint; struct integrity_iint_cache *iint;
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
int must_appraise; int must_appraise;
must_appraise = ima_must_appraise(inode, MAY_ACCESS, FILE_CHECK, NULL); 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) if (!must_appraise)
return; continue;
/* Nothing to do if we can't allocate memory */ /* Nothing to do if we can't allocate memory */
iint = integrity_inode_get(inode); iint = integrity_inode_rb_get(ima_ns->iint_tree, inode);
if (!iint) if (!iint)
return; continue;
/* needed for re-opening empty files */ /* needed for re-opening empty files */
iint->flags |= IMA_NEW_FILE; iint->flags |= IMA_NEW_FILE;
}
up_read(&ima_ns_list_lock);
} }
/** /**
...@@ -766,7 +843,7 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id, ...@@ -766,7 +843,7 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id,
func = read_idmap[read_id] ?: FILE_CHECK; func = read_idmap[read_id] ?: FILE_CHECK;
security_task_getsecid(current, &secid); security_task_getsecid(current, &secid);
return process_measurement(file, current_cred(), secid, NULL, return process_measurement(file, current_cred(), secid, NULL,
0, MAY_READ, func, NULL); 0, MAY_READ, func);
} }
const int read_idmap[READING_MAX_ID] = { const int read_idmap[READING_MAX_ID] = {
...@@ -796,13 +873,14 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size, ...@@ -796,13 +873,14 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
{ {
enum ima_hooks func; enum ima_hooks func;
u32 secid; u32 secid;
struct ima_namespace *ima_ns = get_current_ns();
/* permit signed certs */ /* permit signed certs */
if (!file && read_id == READING_X509_CERTIFICATE) if (!file && read_id == READING_X509_CERTIFICATE)
return 0; return 0;
if (!file || !buf || size == 0) { /* should never happen */ if (!file || !buf || size == 0) { /* should never happen */
if (ima_appraise & IMA_APPRAISE_ENFORCE) if (ima_ns->policy_data->ima_appraise & IMA_APPRAISE_ENFORCE)
return -EACCES; return -EACCES;
return 0; return 0;
} }
...@@ -810,7 +888,7 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size, ...@@ -810,7 +888,7 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
func = read_idmap[read_id] ?: FILE_CHECK; func = read_idmap[read_id] ?: FILE_CHECK;
security_task_getsecid(current, &secid); security_task_getsecid(current, &secid);
return process_measurement(file, current_cred(), secid, buf, size, return process_measurement(file, current_cred(), secid, buf, size,
MAY_READ, func, NULL); MAY_READ, func);
} }
/** /**
...@@ -828,9 +906,16 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size, ...@@ -828,9 +906,16 @@ 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) int ima_load_data(enum kernel_load_data_id id, bool contents)
{ {
bool ima_enforce, sig_enforce; 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_enforce =
(ima_appraise & IMA_APPRAISE_ENFORCE) == IMA_APPRAISE_ENFORCE; (ima_ns->policy_data->ima_appraise & IMA_APPRAISE_ENFORCE) ==
IMA_APPRAISE_ENFORCE;
switch (id) { switch (id) {
case LOADING_KEXEC_IMAGE: case LOADING_KEXEC_IMAGE:
...@@ -840,13 +925,16 @@ int ima_load_data(enum kernel_load_data_id id, bool contents) ...@@ -840,13 +925,16 @@ int ima_load_data(enum kernel_load_data_id id, bool contents)
return -EACCES; return -EACCES;
} }
if (ima_enforce && (ima_appraise & IMA_APPRAISE_KEXEC)) { if (ima_enforce &&
(ima_ns->policy_data->ima_appraise & IMA_APPRAISE_KEXEC)) {
pr_err("impossible to appraise a kernel image without a file descriptor; try using kexec_file_load syscall.\n"); pr_err("impossible to appraise a kernel image without a file descriptor; try using kexec_file_load syscall.\n");
return -EACCES; /* INTEGRITY_UNKNOWN */ return -EACCES; /* INTEGRITY_UNKNOWN */
} }
break; break;
case LOADING_FIRMWARE: case LOADING_FIRMWARE:
if (ima_enforce && (ima_appraise & IMA_APPRAISE_FIRMWARE) && !contents) { if (ima_enforce &&
(ima_ns->policy_data->ima_appraise &
IMA_APPRAISE_FIRMWARE) && !contents) {
pr_err("Prevent firmware sysfs fallback loading.\n"); pr_err("Prevent firmware sysfs fallback loading.\n");
return -EACCES; /* INTEGRITY_UNKNOWN */ return -EACCES; /* INTEGRITY_UNKNOWN */
} }
...@@ -854,8 +942,10 @@ int ima_load_data(enum kernel_load_data_id id, bool contents) ...@@ -854,8 +942,10 @@ int ima_load_data(enum kernel_load_data_id id, bool contents)
case LOADING_MODULE: case LOADING_MODULE:
sig_enforce = is_module_sig_enforced(); sig_enforce = is_module_sig_enforced();
if (ima_enforce && (!sig_enforce if (ima_enforce &&
&& (ima_appraise & IMA_APPRAISE_MODULES))) { (!sig_enforce &&
(ima_ns->policy_data->ima_appraise &
IMA_APPRAISE_MODULES))) {
pr_err("impossible to appraise a module without a file descriptor. sig_enforce kernel parameter might help\n"); pr_err("impossible to appraise a module without a file descriptor. sig_enforce kernel parameter might help\n");
return -EACCES; /* INTEGRITY_UNKNOWN */ return -EACCES; /* INTEGRITY_UNKNOWN */
} }
...@@ -882,9 +972,14 @@ int ima_post_load_data(char *buf, loff_t size, ...@@ -882,9 +972,14 @@ int ima_post_load_data(char *buf, loff_t size,
enum kernel_load_data_id load_id, enum kernel_load_data_id load_id,
char *description) char *description)
{ {
struct ima_namespace *ima_ns = get_current_ns();
if (load_id == LOADING_FIRMWARE) { if (load_id == LOADING_FIRMWARE) {
if ((ima_appraise & IMA_APPRAISE_FIRMWARE) && if (WARN_ON(ima_ns != &init_ima_ns))
(ima_appraise & IMA_APPRAISE_ENFORCE)) { return -EACCES;
if ((ima_ns->policy_data->ima_appraise & IMA_APPRAISE_FIRMWARE) &&
(ima_ns->policy_data->ima_appraise & IMA_APPRAISE_ENFORCE)) {
pr_err("Prevent firmware loading_store.\n"); pr_err("Prevent firmware loading_store.\n");
return -EACCES; /* INTEGRITY_UNKNOWN */ return -EACCES; /* INTEGRITY_UNKNOWN */
} }
...@@ -903,6 +998,7 @@ int ima_post_load_data(char *buf, loff_t size, ...@@ -903,6 +998,7 @@ int ima_post_load_data(char *buf, loff_t size,
* @func: IMA hook * @func: IMA hook
* @pcr: pcr to extend the measurement * @pcr: pcr to extend the measurement
* @keyring: keyring name to determine the action to be performed * @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. * Based on policy, the buffer is measured into the ima log.
*/ */
...@@ -928,7 +1024,7 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size, ...@@ -928,7 +1024,7 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size,
int action = 0; int action = 0;
u32 secid; u32 secid;
if (!ima_policy_flag) if (!ima_ns->policy_data->ima_policy_flag)
return; return;
/* /*
...@@ -941,7 +1037,7 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size, ...@@ -941,7 +1037,7 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size,
if (func) { if (func) {
security_task_getsecid(current, &secid); security_task_getsecid(current, &secid);
action = ima_get_action(inode, current_cred(), secid, 0, func, action = ima_get_action(inode, current_cred(), secid, 0, func,
&pcr, &template, keyring, NULL); &pcr, &template, keyring, ima_ns);
if (!(action & IMA_MEASURE)) if (!(action & IMA_MEASURE))
return; return;
} }
...@@ -1004,6 +1100,11 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size, ...@@ -1004,6 +1100,11 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size,
void ima_kexec_cmdline(int kernel_fd, const void *buf, int size) void ima_kexec_cmdline(int kernel_fd, const void *buf, int size)
{ {
struct fd f; 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) if (!buf || !size)
return; return;
...@@ -1014,10 +1115,31 @@ void ima_kexec_cmdline(int kernel_fd, const void *buf, int size) ...@@ -1014,10 +1115,31 @@ void ima_kexec_cmdline(int kernel_fd, const void *buf, int size)
process_buffer_measurement(file_inode(f.file), buf, size, process_buffer_measurement(file_inode(f.file), buf, size,
"kexec-cmdline", KEXEC_CMDLINE, 0, NULL, "kexec-cmdline", KEXEC_CMDLINE, 0, NULL,
NULL); ima_ns);
fdput(f); 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) static int __init init_ima(void)
{ {
int error; int error;
......
...@@ -181,11 +181,14 @@ int __init ima_init_namespace(void) ...@@ -181,11 +181,14 @@ int __init ima_init_namespace(void)
static void destroy_ima_ns(struct ima_namespace *ns) static void destroy_ima_ns(struct ima_namespace *ns)
{ {
bool is_init_ns = (ns == &init_ima_ns);
dec_ima_namespaces(ns->ucounts); dec_ima_namespaces(ns->ucounts);
put_user_ns(ns->user_ns); put_user_ns(ns->user_ns);
ns_free_inum(&ns->ns); ns_free_inum(&ns->ns);
integrity_iint_tree_free(ns->iint_tree); integrity_iint_tree_free(ns->iint_tree);
kfree(ns->iint_tree); kfree(ns->iint_tree);
ima_delete_ns_rules(ns->policy_data, is_init_ns);
kfree(ns->policy_data); kfree(ns->policy_data);
kfree(ns); kfree(ns);
} }
......
此差异已折叠。
...@@ -110,8 +110,11 @@ bool ima_queue_key(struct key *keyring, const void *payload, ...@@ -110,8 +110,11 @@ bool ima_queue_key(struct key *keyring, const void *payload,
if (!entry) if (!entry)
return false; 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); mutex_lock(&ima_keys_lock);
if (!ima_process_keys) { if (!ima_process_keys && (get_current_ns() == &init_ima_ns)) {
list_add_tail(&entry->list, &ima_keys); list_add_tail(&entry->list, &ima_keys);
queued = true; queued = true;
} }
...@@ -158,12 +161,15 @@ void ima_process_queued_keys(void) ...@@ -158,12 +161,15 @@ void ima_process_queued_keys(void)
list_for_each_entry_safe(entry, tmp, &ima_keys, list) { list_for_each_entry_safe(entry, tmp, &ima_keys, list) {
if (!timer_expired) if (!timer_expired)
/* Queued keys are always measured according to the
* initial namespace policy.
*/
process_buffer_measurement(NULL, entry->payload, process_buffer_measurement(NULL, entry->payload,
entry->payload_len, entry->payload_len,
entry->keyring_name, entry->keyring_name,
KEY_CHECK, 0, KEY_CHECK, 0,
entry->keyring_name, entry->keyring_name,
NULL); &init_ima_ns);
list_del(&entry->list); list_del(&entry->list);
ima_free_key_entry(entry); ima_free_key_entry(entry);
} }
......
...@@ -989,7 +989,7 @@ static void inode_free_by_rcu(struct rcu_head *head) ...@@ -989,7 +989,7 @@ static void inode_free_by_rcu(struct rcu_head *head)
void security_inode_free(struct inode *inode) void security_inode_free(struct inode *inode)
{ {
integrity_inode_free(inode); ima_inode_free(inode);
call_void_hook(inode_free_security, inode); call_void_hook(inode_free_security, inode);
/* /*
* The inode may still be referenced in a path walk and * The inode may still be referenced in a path walk and
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册