Move vfsmount into user_namesapce so that every instance of the virtualized SecurityFS can have this parameter. Use simple_pin_fs only for the init_user_ns expecting that the parent node can be found using the vfsmount from the user_namespace for non-init_user_ns case. Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxxxxx> Signed-off-by: James Bottomley <James.Bottomley@xxxxxxxxxxxxxxxxxxxxx> --- include/linux/user_namespace.h | 3 +++ security/inode.c | 25 +++++++++++++++++-------- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h index 5249db04d62b..89663e6e0e85 100644 --- a/include/linux/user_namespace.h +++ b/include/linux/user_namespace.h @@ -103,6 +103,9 @@ struct user_namespace { #ifdef CONFIG_IMA struct ima_namespace *ima_ns; #endif +#ifdef CONFIG_SECURITYFS + struct vfsmount *securityfs_mount; +#endif } __randomize_layout; struct ucounts { diff --git a/security/inode.c b/security/inode.c index 6c326939750d..f1006cec6ce6 100644 --- a/security/inode.c +++ b/security/inode.c @@ -21,9 +21,9 @@ #include <linux/security.h> #include <linux/lsm_hooks.h> #include <linux/magic.h> +#include <linux/user_namespace.h> -static struct vfsmount *mount; -static int mount_count; +static int securityfs_mount_count; static void securityfs_free_inode(struct inode *inode) { @@ -109,6 +109,7 @@ static struct dentry *securityfs_create_dentry(const char *name, umode_t mode, const struct file_operations *fops, const struct inode_operations *iops) { + struct user_namespace *ns = current_user_ns(); struct dentry *dentry; struct inode *dir, *inode; int error; @@ -118,12 +119,15 @@ static struct dentry *securityfs_create_dentry(const char *name, umode_t mode, pr_debug("securityfs: creating file '%s'\n",name); - error = simple_pin_fs(&fs_type, &mount, &mount_count); - if (error) - return ERR_PTR(error); + if (ns == &init_user_ns) { + error = simple_pin_fs(&fs_type, &ns->securityfs_mount, + &securityfs_mount_count); + if (error) + return ERR_PTR(error); + } if (!parent) - parent = mount->mnt_root; + parent = ns->securityfs_mount->mnt_root; dir = d_inode(parent); @@ -168,7 +172,9 @@ static struct dentry *securityfs_create_dentry(const char *name, umode_t mode, dentry = ERR_PTR(error); out: inode_unlock(dir); - simple_release_fs(&mount, &mount_count); + if (ns == &init_user_ns) + simple_release_fs(&ns->securityfs_mount, + &securityfs_mount_count); return dentry; } @@ -294,6 +300,7 @@ EXPORT_SYMBOL_GPL(securityfs_create_symlink); */ void securityfs_remove(struct dentry *dentry) { + struct user_namespace *ns = dentry->d_sb->s_user_ns; struct inode *dir; if (!dentry || IS_ERR(dentry)) @@ -309,7 +316,9 @@ void securityfs_remove(struct dentry *dentry) dput(dentry); } inode_unlock(dir); - simple_release_fs(&mount, &mount_count); + if (ns == &init_user_ns) + simple_release_fs(&ns->securityfs_mount, + &securityfs_mount_count); } EXPORT_SYMBOL_GPL(securityfs_remove); -- 2.31.1