提交 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,
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);
......@@ -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_inode_free(struct inode *inode)
{
}
static inline bool ima_is_root_namespace(void)
{
return true;
}
#endif /* CONFIG_IMA */
#ifndef CONFIG_IMA_KEXEC
......
......@@ -362,6 +362,13 @@ 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;
......
......@@ -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)
/* 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;
......@@ -69,6 +65,8 @@ 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 */
......@@ -402,6 +400,9 @@ 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;
......@@ -415,6 +416,9 @@ 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)
{
......
......@@ -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_policy_flag;
flags &= ima_ns->policy_data->ima_policy_flag;
return ima_match_policy(inode, cred, secid, func, mask, flags, pcr,
template_desc, keyring, ima_ns);
......
......@@ -21,18 +21,10 @@ 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 = ima_appraise;
int appraisal_state = setup_data->ima_appraise;
if (strncmp(str, "off", 3) == 0)
appraisal_state = 0;
......@@ -52,7 +44,7 @@ static int __init default_appraise_setup(char *str)
pr_info("Secure boot enabled: ignoring ima_appraise=%s option",
str);
} else {
ima_appraise = appraisal_state;
setup_data->ima_appraise = appraisal_state;
}
#endif
if (strcmp(str, "enforce-evm") == 0 ||
......@@ -61,6 +53,11 @@ static int __init default_appraise_setup(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;
......@@ -87,7 +84,10 @@ __setup("ima_appraise_digest_list=", appraise_digest_list_setup);
*/
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)
*
* 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_appraise)
if (!ima_ns->policy_data->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,
NULL);
ima_ns);
}
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, NULL);
pcr, NULL, ima_ns);
}
return rc;
......@@ -381,6 +381,7 @@ 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)
......@@ -509,7 +510,8 @@ 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_appraise & IMA_APPRAISE_FIX) && !try_modsig &&
if ((ima_ns->policy_data->ima_appraise & IMA_APPRAISE_FIX) &&
!try_modsig &&
(!xattr_value ||
xattr_value->type != EVM_IMA_XATTR_DIGSIG)) {
if (!ima_fix_xattr(dentry, iint))
......@@ -574,18 +576,30 @@ 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 (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)
|| !(inode->i_opflags & IOP_XATTR))
if (!S_ISREG(inode->i_mode) ||
!(inode->i_opflags & IOP_XATTR))
return;
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);
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);
}
}
up_read(&ima_ns_list_lock);
}
/*
......@@ -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)
{
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;
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);
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);
}
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,
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)
......@@ -60,6 +70,5 @@ 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,
NULL);
keyring->description, ima_ns);
}
......@@ -167,7 +167,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 & ima_policy_flag))
if (!(ima_digest_list_actions & init_policy_data.ima_policy_flag))
return -EACCES;
while (bufp < bufendp) {
......@@ -383,7 +383,7 @@ void __init ima_load_digest_lists(void)
.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;
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,
ssize_t result;
struct dentry *dentry = file_dentry(file);
int i;
struct ima_namespace *ima_ns = get_current_ns();
/* No partial writes. */
result = -EINVAL;
......@@ -400,7 +401,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_appraise & IMA_APPRAISE_POLICY) {
if (ima_ns->policy_data->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,
......@@ -515,6 +516,7 @@ 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);
......@@ -527,7 +529,7 @@ static int ima_release_data_upload(struct inode *inode, struct file *file)
return 0;
}
if (valid_policy && ima_check_policy(NULL) < 0) {
if (valid_policy && ima_check_policy(ima_ns) < 0) {
cause = "failed";
valid_policy = 0;
}
......
......@@ -118,15 +118,16 @@ static int __init ima_add_boot_aggregate(void)
#ifdef CONFIG_IMA_LOAD_X509
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);
/* load also EVM key to avoid appraisal */
evm_load_x509();
ima_policy_flag |= unset_flags;
init_ima_ns.policy_data->ima_policy_flag |= unset_flags;
}
#endif
......
......@@ -30,12 +30,6 @@
#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 */
......@@ -134,7 +128,8 @@ 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_find(inode);
iint = integrity_iint_rb_find(ima_ns->iint_tree,
inode);
/* IMA_MEASURE is set from reader side */
if (iint && test_bit(IMA_MUST_MEASURE,
&iint->atomic_flags))
......@@ -214,11 +209,38 @@ 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;
......@@ -232,6 +254,9 @@ 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);
}
......@@ -281,10 +306,10 @@ void ima_file_free(struct file *file)
if (unlikely(!(file->f_mode & FMODE_OPENED)))
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;
iint = integrity_iint_find(inode);
iint = integrity_iint_rb_find(ima_ns->iint_tree, inode);
if (!iint)
goto out;
......@@ -293,10 +318,10 @@ void ima_file_free(struct file *file)
put_ima_ns(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)
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)
{
struct inode *inode = file_inode(file);
struct integrity_iint_cache *iint = NULL;
......@@ -312,8 +337,9 @@ static int process_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_policy_flag || !S_ISREG(inode->i_mode))
if (!ima_ns->policy_data->ima_policy_flag)
return 0;
/* Return an IMA_MEASURE, IMA_APPRAISE, IMA_AUDIT action
......@@ -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,
&template_desc, NULL, ima_ns);
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)
return 0;
......@@ -336,7 +363,7 @@ static int process_measurement(struct file *file, const struct cred *cred,
inode_lock(inode);
if (action) {
iint = integrity_inode_get(inode);
iint = integrity_inode_rb_get(ima_ns->iint_tree, inode);
if (!iint)
rc = -ENOMEM;
}
......@@ -351,6 +378,8 @@ static int process_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);
......@@ -478,7 +507,8 @@ static int process_measurement(struct file *file, const struct cred *cred,
if (pathbuf)
__putname(pathbuf);
if (must_appraise) {
if (rc && (ima_appraise & IMA_APPRAISE_ENFORCE))
if (rc &&
(ima_ns->policy_data->ima_appraise & IMA_APPRAISE_ENFORCE))
return -EACCES;
if (file->f_mode & FMODE_WRITE)
set_bit(IMA_UPDATE_XATTR, &iint->atomic_flags);
......@@ -486,6 +516,32 @@ static int process_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)
......@@ -504,7 +560,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, NULL);
0, MAY_EXEC, MMAP_CHECK);
}
return 0;
......@@ -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)
{
struct ima_namespace *ima_ns = get_current_ns();
struct ima_template_desc *template;
struct file *file = vma->vm_file;
char filename[NAME_MAX];
......@@ -536,14 +593,15 @@ int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot)
int pcr;
/* Is mprotect making an mmap'ed file executable? */
if (!(ima_policy_flag & IMA_APPRAISE) || !vma->vm_file ||
!(prot & PROT_EXEC) || (vma->vm_flags & VM_EXEC))
if (!(ima_ns->policy_data->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, NULL);
MMAP_CHECK, &pcr, &template, 0, ima_ns);
/* Is the mmap'ed file in policy? */
if (!(action & (IMA_MEASURE | IMA_APPRAISE_SUBMASK)))
......@@ -582,13 +640,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, NULL);
MAY_EXEC, BPRM_CHECK);
if (ret)
return ret;
security_cred_getsecid(bprm->cred, &secid);
return process_measurement(bprm->file, bprm->cred, secid, NULL, 0,
MAY_EXEC, CREDS_CHECK, NULL);
MAY_EXEC, CREDS_CHECK);
}
/**
......@@ -609,7 +667,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, NULL);
MAY_APPEND), FILE_CHECK);
if (ima_current_is_parser() && !rc)
ima_check_measured_appraised(file);
return rc;
......@@ -618,7 +676,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.
* is in the iint cache of the current IMA namespace.
* @file: pointer to the file
* @buf: buffer in which to store the hash
* @buf_size: length of the buffer
......@@ -636,6 +694,7 @@ 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;
......@@ -643,11 +702,11 @@ int ima_file_hash(struct file *file, char *buf, size_t buf_size)
if (!file)
return -EINVAL;
if (!ima_policy_flag)
if (!ima_ns->policy_data->ima_policy_flag)
return -EOPNOTSUPP;
inode = file_inode(file);
iint = integrity_iint_find(inode);
iint = integrity_iint_rb_find(ima_ns->iint_tree, inode);
if (!iint)
return -EOPNOTSUPP;
......@@ -685,21 +744,30 @@ 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;
must_appraise = ima_must_appraise(inode, MAY_ACCESS, FILE_CHECK, NULL);
if (!must_appraise)
return;
down_read(&ima_ns_list_lock);
list_for_each_entry(ima_ns, &ima_ns_list, list) {
if (atomic_read(&ima_ns->inactive))
continue;
/* Nothing to do if we can't allocate memory */
iint = integrity_inode_get(inode);
if (!iint)
return;
must_appraise = ima_must_appraise(inode, MAY_ACCESS,
FILE_CHECK, ima_ns);
if (!must_appraise)
continue;
/* Nothing to do if we can't allocate memory */
iint = integrity_inode_rb_get(ima_ns->iint_tree, inode);
if (!iint)
continue;
/* needed for writing the security xattrs */
set_bit(IMA_UPDATE_XATTR, &iint->atomic_flags);
iint->ima_file_status = INTEGRITY_PASS;
/* 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);
}
/**
......@@ -711,21 +779,30 @@ 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;
must_appraise = ima_must_appraise(inode, MAY_ACCESS, FILE_CHECK, NULL);
if (!must_appraise)
return;
down_read(&ima_ns_list_lock);
list_for_each_entry(ima_ns, &ima_ns_list, list) {
if (atomic_read(&ima_ns->inactive))
continue;
/* Nothing to do if we can't allocate memory */
iint = integrity_inode_get(inode);
if (!iint)
return;
must_appraise = ima_must_appraise(inode, MAY_ACCESS,
FILE_CHECK, ima_ns);
if (!must_appraise)
continue;
/* needed for re-opening empty files */
iint->flags |= IMA_NEW_FILE;
/* Nothing to do if we can't allocate memory */
iint = integrity_inode_rb_get(ima_ns->iint_tree, inode);
if (!iint)
continue;
/* needed for re-opening empty files */
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,
func = read_idmap[read_id] ?: FILE_CHECK;
security_task_getsecid(current, &secid);
return process_measurement(file, current_cred(), secid, NULL,
0, MAY_READ, func, NULL);
0, MAY_READ, func);
}
const int read_idmap[READING_MAX_ID] = {
......@@ -796,13 +873,14 @@ 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_appraise & IMA_APPRAISE_ENFORCE)
if (ima_ns->policy_data->ima_appraise & IMA_APPRAISE_ENFORCE)
return -EACCES;
return 0;
}
......@@ -810,7 +888,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, NULL);
MAY_READ, func);
}
/**
......@@ -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)
{
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_appraise & IMA_APPRAISE_ENFORCE) == IMA_APPRAISE_ENFORCE;
(ima_ns->policy_data->ima_appraise & IMA_APPRAISE_ENFORCE) ==
IMA_APPRAISE_ENFORCE;
switch (id) {
case LOADING_KEXEC_IMAGE:
......@@ -840,13 +925,16 @@ int ima_load_data(enum kernel_load_data_id id, bool contents)
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");
return -EACCES; /* INTEGRITY_UNKNOWN */
}
break;
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");
return -EACCES; /* INTEGRITY_UNKNOWN */
}
......@@ -854,8 +942,10 @@ 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_appraise & IMA_APPRAISE_MODULES))) {
if (ima_enforce &&
(!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");
return -EACCES; /* INTEGRITY_UNKNOWN */
}
......@@ -882,9 +972,14 @@ 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 ((ima_appraise & IMA_APPRAISE_FIRMWARE) &&
(ima_appraise & IMA_APPRAISE_ENFORCE)) {
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)) {
pr_err("Prevent firmware loading_store.\n");
return -EACCES; /* INTEGRITY_UNKNOWN */
}
......@@ -903,6 +998,7 @@ 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.
*/
......@@ -928,7 +1024,7 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size,
int action = 0;
u32 secid;
if (!ima_policy_flag)
if (!ima_ns->policy_data->ima_policy_flag)
return;
/*
......@@ -941,7 +1037,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, NULL);
&pcr, &template, keyring, ima_ns);
if (!(action & IMA_MEASURE))
return;
}
......@@ -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)
{
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;
......@@ -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,
"kexec-cmdline", KEXEC_CMDLINE, 0, NULL,
NULL);
ima_ns);
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;
......
......@@ -181,11 +181,14 @@ 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);
}
......
此差异已折叠。
......@@ -110,8 +110,11 @@ 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) {
if (!ima_process_keys && (get_current_ns() == &init_ima_ns)) {
list_add_tail(&entry->list, &ima_keys);
queued = true;
}
......@@ -158,12 +161,15 @@ 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,
NULL);
&init_ima_ns);
list_del(&entry->list);
ima_free_key_entry(entry);
}
......
......@@ -989,7 +989,7 @@ static void inode_free_by_rcu(struct rcu_head *head)
void security_inode_free(struct inode *inode)
{
integrity_inode_free(inode);
ima_inode_free(inode);
call_void_hook(inode_free_security, inode);
/*
* 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.
先完成此消息的编辑!
想要评论请 注册