From 18c2ceb526b5651e31390d796fffc0fb47fe0b4e Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sun, 24 Mar 2013 14:28:27 -0700 Subject: [PATCH] --- yaml --- r: 361884 b: refs/heads/master c: 87a8ebd637dafc255070f503909a053cf0d98d3f h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/fs/namespace.c | 21 +++++++++++++++++++++ trunk/fs/proc/root.c | 4 ++++ trunk/fs/sysfs/mount.c | 4 ++++ trunk/include/linux/user_namespace.h | 4 ++++ trunk/kernel/user.c | 2 ++ trunk/kernel/user_namespace.c | 2 ++ 7 files changed, 38 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index 5e3707847692..598d0793f908 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: a636b702ed1805e988ad3d8ff8b52c060f8b341c +refs/heads/master: 87a8ebd637dafc255070f503909a053cf0d98d3f diff --git a/trunk/fs/namespace.c b/trunk/fs/namespace.c index 968d4c5eae03..d581e45c0a9f 100644 --- a/trunk/fs/namespace.c +++ b/trunk/fs/namespace.c @@ -2763,6 +2763,27 @@ bool current_chrooted(void) return chrooted; } +void update_mnt_policy(struct user_namespace *userns) +{ + struct mnt_namespace *ns = current->nsproxy->mnt_ns; + struct mount *mnt; + + down_read(&namespace_sem); + list_for_each_entry(mnt, &ns->list, mnt_list) { + switch (mnt->mnt.mnt_sb->s_magic) { + case SYSFS_MAGIC: + userns->may_mount_sysfs = true; + break; + case PROC_SUPER_MAGIC: + userns->may_mount_proc = true; + break; + } + if (userns->may_mount_sysfs && userns->may_mount_proc) + break; + } + up_read(&namespace_sem); +} + static void *mntns_get(struct task_struct *task) { struct mnt_namespace *ns = NULL; diff --git a/trunk/fs/proc/root.c b/trunk/fs/proc/root.c index c6e9fac26bac..9c7fab1d23f0 100644 --- a/trunk/fs/proc/root.c +++ b/trunk/fs/proc/root.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -108,6 +109,9 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, } else { ns = task_active_pid_ns(current); options = data; + + if (!current_user_ns()->may_mount_proc) + return ERR_PTR(-EPERM); } sb = sget(fs_type, proc_test_super, proc_set_super, flags, ns); diff --git a/trunk/fs/sysfs/mount.c b/trunk/fs/sysfs/mount.c index 8d924b5ec733..afd83273e6ce 100644 --- a/trunk/fs/sysfs/mount.c +++ b/trunk/fs/sysfs/mount.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "sysfs.h" @@ -111,6 +112,9 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type, struct super_block *sb; int error; + if (!(flags & MS_KERNMOUNT) && !current_user_ns()->may_mount_sysfs) + return ERR_PTR(-EPERM); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return ERR_PTR(-ENOMEM); diff --git a/trunk/include/linux/user_namespace.h b/trunk/include/linux/user_namespace.h index 4ce009324933..b6b215f13b45 100644 --- a/trunk/include/linux/user_namespace.h +++ b/trunk/include/linux/user_namespace.h @@ -26,6 +26,8 @@ struct user_namespace { kuid_t owner; kgid_t group; unsigned int proc_inum; + bool may_mount_sysfs; + bool may_mount_proc; }; extern struct user_namespace init_user_ns; @@ -82,4 +84,6 @@ static inline void put_user_ns(struct user_namespace *ns) #endif +void update_mnt_policy(struct user_namespace *userns); + #endif /* _LINUX_USER_H */ diff --git a/trunk/kernel/user.c b/trunk/kernel/user.c index e81978e8c03b..8e635a18ab52 100644 --- a/trunk/kernel/user.c +++ b/trunk/kernel/user.c @@ -51,6 +51,8 @@ struct user_namespace init_user_ns = { .owner = GLOBAL_ROOT_UID, .group = GLOBAL_ROOT_GID, .proc_inum = PROC_USER_INIT_INO, + .may_mount_sysfs = true, + .may_mount_proc = true, }; EXPORT_SYMBOL_GPL(init_user_ns); diff --git a/trunk/kernel/user_namespace.c b/trunk/kernel/user_namespace.c index 0f1e42884577..a54f26f82eb2 100644 --- a/trunk/kernel/user_namespace.c +++ b/trunk/kernel/user_namespace.c @@ -96,6 +96,8 @@ int create_user_ns(struct cred *new) set_cred_user_ns(new, ns); + update_mnt_policy(ns); + return 0; }