@@ -66,6 +66,9 @@ static inline const char * const *arch_get_ima_policy(void)
}
#endif
+extern int ima_securityfs_init(struct user_namespace *user_ns,
+ struct dentry *root);
+
#else
static inline enum hash_algo ima_get_current_hash_algo(void)
{
@@ -154,6 +157,11 @@ static inline int ima_measure_critical_data(const char *event_label,
return -ENOENT;
}
+static inline int ima_securityfs_init(struct user_namespace *ns, struct dentry *root)
+{
+ return 0;
+}
+
#endif /* CONFIG_IMA */
#ifndef CONFIG_IMA_KEXEC
@@ -221,7 +229,8 @@ struct ima_h_table {
};
enum {
- IMAFS_DENTRY_DIR = 0,
+ IMAFS_DENTRY_INTEGRITY_DIR = 0,
+ IMAFS_DENTRY_DIR,
IMAFS_DENTRY_SYMLINK,
IMAFS_DENTRY_BINARY_RUNTIME_MEASUREMENTS,
IMAFS_DENTRY_ASCII_RUNTIME_MEASUREMENTS,
@@ -336,6 +345,7 @@ static inline struct ima_namespace *get_current_ns(void)
{
return &init_ima_ns;
}
+
#endif /* CONFIG_IMA_NS */
#if defined(CONFIG_IMA_APPRAISE) && defined(CONFIG_INTEGRITY_TRUSTED_KEYRING)
@@ -16,6 +16,7 @@
#include <linux/fs_context.h>
#include <linux/mount.h>
#include <linux/pagemap.h>
+#include <linux/ima.h>
#include <linux/init.h>
#include <linux/namei.h>
#include <linux/security.h>
@@ -41,6 +42,7 @@ static const struct super_operations securityfs_super_operations = {
static int securityfs_fill_super(struct super_block *sb, struct fs_context *fc)
{
static const struct tree_descr files[] = {{""}};
+ struct user_namespace *ns = fc->user_ns;
int error;
error = simple_fill_super(sb, SECURITYFS_MAGIC, files);
@@ -49,7 +51,10 @@ static int securityfs_fill_super(struct super_block *sb, struct fs_context *fc)
sb->s_op = &securityfs_super_operations;
- return 0;
+ if (ns != &init_user_ns)
+ error = ima_securityfs_init(ns, sb->s_root);
+
+ return error;
}
static int securityfs_get_tree(struct fs_context *fc)
@@ -97,11 +102,15 @@ static struct file_system_type fs_type = {
* securityfs_create_dir() function is recommended to be used
* instead).
*
- * This function returns a pointer to a dentry if it succeeds. This
+ * This function returns a pointer to a dentry if it succeeds. If the
+ * dentry was created while the init_user_ns was active, then this
* pointer must be passed to the securityfs_remove() function when the
* file is to be removed (no automatic cleanup happens if your module
- * is unloaded, you are responsible here). If an error occurs, the
- * function will return the error value (via ERR_PTR).
+ * is unloaded, you are responsible here). If any other user namespace
+ * was active then the dentry may be removed using securityfs_remove()
+ * when a module is removed but no cleanup must be done once the
+ * superblock was delete since then it will be deleted automatically.
+ * If an error occurs, the function will return the error value (via ERR_PTR).
*
* If securityfs is not enabled in the kernel, the value %-ENODEV is
* returned.
@@ -169,7 +178,8 @@ static struct dentry *securityfs_create_dentry(const char *name, umode_t mode,
inode->i_fop = fops;
}
d_instantiate(dentry, inode);
- dget(dentry);
+ if (ns == &init_user_ns)
+ dget(dentry);
inode_unlock(dir);
return dentry;
@@ -447,8 +447,12 @@ static const struct file_operations ima_measure_policy_ops = {
.llseek = generic_file_llseek,
};
-static void ima_fs_ns_free_dentries(struct ima_namespace *ns)
+/* Remove the dentries. In case user_ns == &init_user_ns this function
+ * does not need to be called since there's one less reference to dentries.
+ */
+static void ima_fs_ns_free_dentries(struct user_namespace *user_ns)
{
+ struct ima_namespace *ns = user_ns->ima_ns;
int i;
for (i = IMAFS_DENTRY_LAST - 1; i >= 0; i--)
@@ -457,18 +461,35 @@ static void ima_fs_ns_free_dentries(struct ima_namespace *ns)
memset(ns->dentry, 0, sizeof(ns->dentry));
}
-static int __init ima_securityfs_init(struct user_namespace *user_ns)
+int ima_securityfs_init(struct user_namespace *user_ns, struct dentry *root)
{
struct ima_namespace *ns = user_ns->ima_ns;
struct dentry *ima_dir;
- ns->dentry[IMAFS_DENTRY_DIR] = securityfs_create_dir("ima", integrity_dir);
+ /* already initialized? */
+ if (ns->dentry[IMAFS_DENTRY_INTEGRITY_DIR])
+ return 0;
+
+ /* FIXME: update when evm and integrity are namespaced */
+ if (user_ns != &init_user_ns) {
+ ns->dentry[IMAFS_DENTRY_INTEGRITY_DIR] =
+ securityfs_create_dir("integrity", root);
+ if (IS_ERR(ns->dentry[IMAFS_DENTRY_INTEGRITY_DIR])) {
+ ns->dentry[IMAFS_DENTRY_INTEGRITY_DIR] = NULL;
+ return -1;
+ }
+ } else
+ ns->dentry[IMAFS_DENTRY_INTEGRITY_DIR] = integrity_dir;
+
+ ns->dentry[IMAFS_DENTRY_DIR] =
+ securityfs_create_dir("ima",
+ ns->dentry[IMAFS_DENTRY_INTEGRITY_DIR]);
if (IS_ERR(ns->dentry[IMAFS_DENTRY_DIR]))
- return -1;
+ goto out;
ima_dir = ns->dentry[IMAFS_DENTRY_DIR];
ns->dentry[IMAFS_DENTRY_SYMLINK] =
- securityfs_create_symlink("ima", NULL, "integrity/ima", NULL);
+ securityfs_create_symlink("ima", root, "integrity/ima", NULL);
if (IS_ERR(ns->dentry[IMAFS_DENTRY_SYMLINK]))
goto out;
@@ -508,11 +529,11 @@ static int __init ima_securityfs_init(struct user_namespace *user_ns)
return 0;
out:
- ima_fs_ns_free_dentries(ns);
+ ima_fs_ns_free_dentries(user_ns);
return -1;
}
int __init ima_fs_init(void)
{
- return ima_securityfs_init(&init_user_ns);
+ return ima_securityfs_init(&init_user_ns, NULL);
}