if (!error) {
fsnotify_change(dentry, ia_valid);
- ima_inode_post_setattr(dentry);
+ ima_inode_post_setattr(mnt_userns, dentry);
evm_inode_post_setattr(dentry, ia_valid);
}
inode->i_state |= I_LINKABLE;
spin_unlock(&inode->i_lock);
}
- ima_post_create_tmpfile(inode);
+ ima_post_create_tmpfile(mnt_userns, inode);
return child;
out_err:
error = vfs_create(mnt_userns, path.dentry->d_inode,
dentry, mode, true);
if (!error)
- ima_post_path_mknod(dentry);
+ ima_post_path_mknod(mnt_userns, dentry);
break;
case S_IFCHR: case S_IFBLK:
error = vfs_mknod(mnt_userns, path.dentry->d_inode,
#ifdef CONFIG_IMA
extern int ima_bprm_check(struct linux_binprm *bprm);
extern int ima_file_check(struct file *file, int mask);
-extern void ima_post_create_tmpfile(struct inode *inode);
+extern void ima_post_create_tmpfile(struct user_namespace *mnt_userns,
+ struct inode *inode);
extern void ima_file_free(struct file *file);
extern int ima_file_mmap(struct file *file, unsigned long prot);
extern int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot);
bool contents);
extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
enum kernel_read_file_id id);
-extern void ima_post_path_mknod(struct dentry *dentry);
+extern void ima_post_path_mknod(struct user_namespace *mnt_userns,
+ struct dentry *dentry);
extern int ima_file_hash(struct file *file, char *buf, size_t buf_size);
extern int ima_inode_hash(struct inode *inode, char *buf, size_t buf_size);
extern void ima_kexec_cmdline(int kernel_fd, const void *buf, int size);
return 0;
}
-static inline void ima_post_create_tmpfile(struct inode *inode)
+static inline void ima_post_create_tmpfile(struct user_namespace *mnt_userns,
+ struct inode *inode)
{
}
return 0;
}
-static inline void ima_post_path_mknod(struct dentry *dentry)
+static inline void ima_post_path_mknod(struct user_namespace *mnt_userns,
+ struct dentry *dentry)
{
return;
}
#ifdef CONFIG_IMA_APPRAISE
extern bool is_ima_appraise_enabled(void);
-extern void ima_inode_post_setattr(struct dentry *dentry);
+extern void ima_inode_post_setattr(struct user_namespace *mnt_userns,
+ struct dentry *dentry);
extern int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
const void *xattr_value, size_t xattr_value_len);
extern int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name);
return 0;
}
-static inline void ima_inode_post_setattr(struct dentry *dentry)
+static inline void ima_inode_post_setattr(struct user_namespace *mnt_userns,
+ struct dentry *dentry)
{
return;
}
#endif /* CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS */
/* LIM API function definitions */
-int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
- int mask, enum ima_hooks func, int *pcr,
+int ima_get_action(struct user_namespace *mnt_userns, struct inode *inode,
+ const struct cred *cred, u32 secid, int mask,
+ enum ima_hooks func, int *pcr,
struct ima_template_desc **template_desc,
const char *keyring);
int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func);
struct evm_ima_xattr_data *xattr_value,
int xattr_len, const struct modsig *modsig, int pcr,
struct ima_template_desc *template_desc);
-void process_buffer_measurement(struct inode *inode, const void *buf, int size,
+void process_buffer_measurement(struct user_namespace *mnt_userns,
+ struct inode *inode, const void *buf, int size,
const char *eventname, enum ima_hooks func,
int pcr, const char *keyring);
void ima_audit_measurement(struct integrity_iint_cache *iint,
const char *ima_d_path(const struct path *path, char **pathbuf, char *filename);
/* IMA policy related functions */
-int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
- enum ima_hooks func, int mask, int flags, int *pcr,
+int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode,
+ const struct cred *cred, u32 secid, enum ima_hooks func,
+ int mask, int flags, int *pcr,
struct ima_template_desc **template_desc,
const char *keyring);
void ima_init_policy(void);
struct file *file, const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value,
int xattr_len, const struct modsig *modsig);
-int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func);
+int ima_must_appraise(struct user_namespace *mnt_userns, struct inode *inode,
+ int mask, enum ima_hooks func);
void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file);
enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
enum ima_hooks func);
return INTEGRITY_UNKNOWN;
}
-static inline int ima_must_appraise(struct inode *inode, int mask,
+static inline int ima_must_appraise(struct user_namespace *mnt_userns,
+ struct inode *inode, int mask,
enum ima_hooks func)
{
return 0;
/**
* ima_get_action - appraise & measure decision based on policy.
+ * @mnt_userns: user namespace of the mount the inode was found from
* @inode: pointer to the inode associated with the object being validated
* @cred: pointer to credentials structure to validate
* @secid: secid of the task being validated
* Returns IMA_MEASURE, IMA_APPRAISE mask.
*
*/
-int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
- int mask, enum ima_hooks func, int *pcr,
+int ima_get_action(struct user_namespace *mnt_userns, struct inode *inode,
+ const struct cred *cred, u32 secid, int mask,
+ enum ima_hooks func, int *pcr,
struct ima_template_desc **template_desc,
const char *keyring)
{
flags &= ima_policy_flag;
- return ima_match_policy(inode, cred, secid, func, mask, flags, pcr,
- template_desc, keyring);
+ return ima_match_policy(mnt_userns, inode, cred, secid, func, mask,
+ flags, pcr, template_desc, keyring);
}
/*
*
* Return 1 to appraise or hash
*/
-int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func)
+int ima_must_appraise(struct user_namespace *mnt_userns, struct inode *inode,
+ int mask, enum ima_hooks func)
{
u32 secid;
return 0;
security_task_getsecid(current, &secid);
- return ima_match_policy(inode, current_cred(), secid, func, mask,
- IMA_APPRAISE | IMA_HASH, NULL, NULL, NULL);
+ return ima_match_policy(mnt_userns, inode, current_cred(), secid, func,
+ mask, IMA_APPRAISE | IMA_HASH, NULL, NULL, NULL);
}
static int ima_fix_xattr(struct dentry *dentry,
rc = is_binary_blacklisted(digest, digestsize);
if ((rc == -EPERM) && (iint->flags & IMA_MEASURE))
- process_buffer_measurement(NULL, digest, digestsize,
+ process_buffer_measurement(&init_user_ns, NULL, digest, digestsize,
"blacklisted-hash", NONE,
pcr, NULL);
}
/**
* ima_inode_post_setattr - reflect file metadata changes
+ * @mnt_userns: user namespace of the mount the inode was found from
* @dentry: pointer to the affected dentry
*
* Changes to a dentry's metadata might result in needing to appraise.
* This function is called from notify_change(), which expects the caller
* to lock the inode's i_mutex.
*/
-void ima_inode_post_setattr(struct dentry *dentry)
+void ima_inode_post_setattr(struct user_namespace *mnt_userns,
+ struct dentry *dentry)
{
struct inode *inode = d_backing_inode(dentry);
struct integrity_iint_cache *iint;
|| !(inode->i_opflags & IOP_XATTR))
return;
- action = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR);
+ action = ima_must_appraise(mnt_userns, inode, MAY_ACCESS, POST_SETATTR);
if (!action)
__vfs_removexattr(&init_user_ns, dentry, XATTR_NAME_IMA);
iint = integrity_iint_find(inode);
*/
#include <keys/asymmetric-type.h>
+#include <linux/user_namespace.h>
#include "ima.h"
/**
* if the IMA policy is configured to measure a key linked
* to the given keyring.
*/
- process_buffer_measurement(NULL, payload, payload_len,
+ process_buffer_measurement(&init_user_ns, NULL, payload, payload_len,
keyring->description, KEY_CHECK, 0,
keyring->description);
}
* bitmask based on the appraise/audit/measurement policy.
* Included is the appraise submask.
*/
- action = ima_get_action(inode, cred, secid, mask, func, &pcr,
- &template_desc, NULL);
+ action = ima_get_action(file_mnt_user_ns(file), inode, cred, secid,
+ mask, func, &pcr, &template_desc, NULL);
violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) &&
(ima_policy_flag & IMA_MEASURE));
if (!action && !violation_check)
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);
+ action = ima_get_action(file_mnt_user_ns(vma->vm_file), inode,
+ current_cred(), secid, MAY_EXEC, MMAP_CHECK,
+ &pcr, &template, 0);
/* Is the mmap'ed file in policy? */
if (!(action & (IMA_MEASURE | IMA_APPRAISE_SUBMASK)))
/**
* ima_post_create_tmpfile - mark newly created tmpfile as new
+ * @mnt_userns: user namespace of the mount the inode was found from
* @file : newly created tmpfile
*
* No measuring, appraising or auditing of newly created tmpfiles is needed.
* Skip calling process_measurement(), but indicate which newly, created
* tmpfiles are in policy.
*/
-void ima_post_create_tmpfile(struct inode *inode)
+void ima_post_create_tmpfile(struct user_namespace *mnt_userns,
+ struct inode *inode)
{
struct integrity_iint_cache *iint;
int must_appraise;
- must_appraise = ima_must_appraise(inode, MAY_ACCESS, FILE_CHECK);
+ must_appraise = ima_must_appraise(mnt_userns, inode, MAY_ACCESS,
+ FILE_CHECK);
if (!must_appraise)
return;
/**
* ima_post_path_mknod - mark as a new inode
+ * @mnt_userns: user namespace of the mount the inode was found from
* @dentry: newly created dentry
*
* Mark files created via the mknodat syscall as new, so that the
* file data can be written later.
*/
-void ima_post_path_mknod(struct dentry *dentry)
+void ima_post_path_mknod(struct user_namespace *mnt_userns,
+ struct dentry *dentry)
{
struct integrity_iint_cache *iint;
struct inode *inode = dentry->d_inode;
int must_appraise;
- must_appraise = ima_must_appraise(inode, MAY_ACCESS, FILE_CHECK);
+ must_appraise = ima_must_appraise(mnt_userns, inode, MAY_ACCESS,
+ FILE_CHECK);
if (!must_appraise)
return;
/*
* process_buffer_measurement - Measure the buffer to ima log.
+ * @mnt_userns: user namespace of the mount the inode was found from
* @inode: inode associated with the object being measured (NULL for KEY_CHECK)
* @buf: pointer to the buffer that needs to be added to the log.
* @size: size of buffer(in bytes).
*
* Based on policy, the buffer is measured into the ima log.
*/
-void process_buffer_measurement(struct inode *inode, const void *buf, int size,
+void process_buffer_measurement(struct user_namespace *mnt_userns,
+ struct inode *inode, const void *buf, int size,
const char *eventname, enum ima_hooks func,
int pcr, const char *keyring)
{
*/
if (func) {
security_task_getsecid(current, &secid);
- action = ima_get_action(inode, current_cred(), secid, 0, func,
- &pcr, &template, keyring);
+ action = ima_get_action(mnt_userns, inode, current_cred(),
+ secid, 0, func, &pcr, &template,
+ keyring);
if (!(action & IMA_MEASURE))
return;
}
if (!f.file)
return;
- process_buffer_measurement(file_inode(f.file), buf, size,
- "kexec-cmdline", KEXEC_CMDLINE, 0, NULL);
+ process_buffer_measurement(file_mnt_user_ns(f.file), file_inode(f.file),
+ buf, size, "kexec-cmdline", KEXEC_CMDLINE, 0,
+ NULL);
fdput(f);
}
/**
* ima_match_rules - determine whether an inode matches the policy rule.
* @rule: a pointer to a rule
+ * @mnt_userns: user namespace of the mount the inode was found from
* @inode: a pointer to an inode
* @cred: a pointer to a credentials structure for user validation
* @secid: the secid of the task to be validated
*
* Returns true on rule match, false on failure.
*/
-static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
- const struct cred *cred, u32 secid,
- enum ima_hooks func, int mask,
+static bool ima_match_rules(struct ima_rule_entry *rule,
+ struct user_namespace *mnt_userns,
+ struct inode *inode, const struct cred *cred,
+ u32 secid, enum ima_hooks func, int mask,
const char *keyring)
{
int i;
}
if ((rule->flags & IMA_FOWNER) &&
- !rule->fowner_op(inode->i_uid, rule->fowner))
+ !rule->fowner_op(i_uid_into_mnt(mnt_userns, inode), rule->fowner))
return false;
for (i = 0; i < MAX_LSM_RULES; i++) {
int rc = 0;
/**
* ima_match_policy - decision based on LSM and other conditions
+ * @mnt_userns: user namespace of the mount the inode was found from
* @inode: pointer to an inode for which the policy decision is being made
* @cred: pointer to a credentials structure for which the policy decision is
* being made
* list when walking it. Reads are many orders of magnitude more numerous
* than writes so ima_match_policy() is classical RCU candidate.
*/
-int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
- enum ima_hooks func, int mask, int flags, int *pcr,
+int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode,
+ const struct cred *cred, u32 secid, enum ima_hooks func,
+ int mask, int flags, int *pcr,
struct ima_template_desc **template_desc,
const char *keyring)
{
if (!(entry->action & actmask))
continue;
- if (!ima_match_rules(entry, inode, cred, secid, func, mask,
- keyring))
+ if (!ima_match_rules(entry, mnt_userns, inode, cred, secid,
+ func, mask, keyring))
continue;
action |= entry->flags & IMA_ACTION_FLAGS;
* Enables deferred processing of keys
*/
+#include <linux/user_namespace.h>
#include <linux/workqueue.h>
#include <keys/asymmetric-type.h>
#include "ima.h"
list_for_each_entry_safe(entry, tmp, &ima_keys, list) {
if (!timer_expired)
- process_buffer_measurement(NULL, entry->payload,
+ process_buffer_measurement(&init_user_ns, NULL,
+ entry->payload,
entry->payload_len,
entry->keyring_name,
KEY_CHECK, 0,