{"push_id":1144821201,"size":4,"distinct_size":4,"ref":"refs/heads/real","head":"3ef7f3fe840357aab02a815e2d903497ad5dffcb","before":"ee4ab35ae92045f36bc5dfb4d904a20397b115a2","commits":[{"sha":"d75c0a5f444c442c97d31d2697fa8ee2c9461776","author":{"name":"robcore","email":"a3b05a675e90e628f2d9df6520db16da9bff1bff@gmail.com"},"message":"From 57e87fa69d662894bdea2118e20b05e5fbf9807b Mon Sep 17 00:00:00 2001\nFrom: Al Viro <viro@zeniv.linux.org.uk>\nDate: Fri, 21 Sep 2012 08:19:02 -0400\nSubject: [PATCH 5967/6000] do_add_mount()/umount -l races\n\nnormally we deal with lock_mount()/umount races by checking that\nmountpoint to be is still in our namespace after lock_mount() has\nbeen done.  However, do_add_mount() skips that check when called\nwith MNT_SHRINKABLE in flags (i.e. from finish_automount()).  The\nreason is that ->mnt_ns may be a temporary namespace created exactly\nto contain automounts a-la NFS4 referral handling.  It's not the\nnamespace of the caller, though, so check_mnt() would fail here.\nWe still need to check that ->mnt_ns is non-NULL in that case,\nthough.\n\nSigned-off-by: Al Viro <viro@zeniv.linux.org.uk>\n(cherry picked from commit 156cacb1d0d36b0d0582d9e798e58e0044f516b3)\n---\n fs/namespace.c | 10 ++++++++--\n 1 file changed, 8 insertions(+), 2 deletions(-)\n\ndiff --git a/fs/namespace.c b/fs/namespace.c\nindex c53d338..e5b9b09 100644\n--- a/fs/namespace.c\n+++ b/fs/namespace.c\n@@ -1829,8 +1829,14 @@ static int do_add_mount(struct mount *newmnt, struct path *path, int mnt_flags)\n \t\treturn err;\n\n \terr = -EINVAL;\n-\tif (!(mnt_flags & MNT_SHRINKABLE) && !check_mnt(real_mount(path->mnt)))\n-\t\tgoto unlock;\n+\tif (unlikely(!check_mnt(real_mount(path->mnt)))) {\n+\t\t/* that's acceptable only for automounts done in private ns */\n+\t\tif (!(mnt_flags & MNT_SHRINKABLE))\n+\t\t\tgoto unlock;\n+\t\t/* ... and for those we'd better have mountpoint still alive */\n+\t\tif (!real_mount(path->mnt)->mnt_ns)\n+\t\t\tgoto unlock;\n+\t}\n\n \t/* Refuse the same filesystem on the same mount point */\n \terr = -EBUSY;\n--\n2.8.1","distinct":true,"url":"https://api.github.com/repos/robcore/Hulk-Kernel-V2/commits/d75c0a5f444c442c97d31d2697fa8ee2c9461776"},{"sha":"b1e42b0ff9ebe98adb5c3950ce21e324e06022ae","author":{"name":"robcore","email":"a3b05a675e90e628f2d9df6520db16da9bff1bff@gmail.com"},"message":"From cd0ed7c2842b24434f84a676a6431f3e18147749 Mon Sep 17 00:00:00 2001\nFrom: \"Eric W. Biederman\" <ebiederm@xmission.com>\nDate: Sun, 7 Mar 2010 18:49:36 -0800\nSubject: [PATCH 5969/6000] vfs: Add setns support for the mount namespace\n\nsetns support for the mount namespace is a little tricky as an\narbitrary decision must be made about what to set fs->root and\nfs->pwd to, as there is no expectation of a relationship between\nthe two mount namespaces.  Therefore I arbitrarily find the root\nmount point, and follow every mount on top of it to find the top\nof the mount stack.  Then I set fs->root and fs->pwd to that\nlocation.  The topmost root of the mount stack seems like a\nreasonable place to be.\n\nBind mount support for the mount namespace inodes has the\npossibility of creating circular dependencies between mount\nnamespaces.  Circular dependencies can result in loops that\nprevent mount namespaces from every being freed.  I avoid\ncreating those circular dependencies by adding a sequence number\nto the mount namespace and require all bind mounts be of a\nyounger mount namespace into an older mount namespace.\n\nAdd a helper function proc_ns_inode so it is possible to\ndetect when we are attempting to bind mound a namespace inode.\n\nAcked-by: Serge Hallyn <serge.hallyn@canonical.com>\nSigned-off-by: Eric W. Biederman <ebiederm@xmission.com>\n(cherry picked from commit 8823c079ba7136dc1948d6f6dcb5f8022bde438e)\n---\n fs/mount.h              |  1 +\n fs/namespace.c          | 95 +++++++++++++++++++++++++++++++++++++++++++++++++\n fs/proc/namespaces.c    |  8 +++++\n include/linux/proc_fs.h |  8 +++++\n 4 files changed, 112 insertions(+)\n\ndiff --git a/fs/mount.h b/fs/mount.h\nindex 4f291f9..e9c37dd 100644\n--- a/fs/mount.h\n+++ b/fs/mount.h\n@@ -6,6 +6,7 @@ struct mnt_namespace {\n \tatomic_t\t\tcount;\n \tstruct mount *\troot;\n \tstruct list_head\tlist;\n+\tu64\t\t\tseq;\t/* Sequence number to prevent loops */\n \twait_queue_head_t poll;\n \tint event;\n };\ndiff --git a/fs/namespace.c b/fs/namespace.c\nindex a855ddf..c633e14 100644\n--- a/fs/namespace.c\n+++ b/fs/namespace.c\n@@ -20,6 +20,7 @@\n #include <linux/fs_struct.h>\t/* get_fs_root et.al. */\n #include <linux/fsnotify.h>\t/* fsnotify_vfsmount_delete */\n #include <linux/uaccess.h>\n+#include <linux/proc_fs.h>\n #include \"pnode.h\"\n #include \"internal.h\"\n\n@@ -1251,6 +1252,26 @@ static int mount_is_safe(struct path *path)\n #endif\n }\n\n+static bool mnt_ns_loop(struct path *path)\n+{\n+\t/* Could bind mounting the mount namespace inode cause a\n+\t * mount namespace loop?\n+\t */\n+\tstruct inode *inode = path->dentry->d_inode;\n+\tstruct proc_inode *ei;\n+\tstruct mnt_namespace *mnt_ns;\n+\n+\tif (!proc_ns_inode(inode))\n+\t\treturn false;\n+\n+\tei = PROC_I(inode);\n+\tif (ei->ns_ops != &mntns_operations)\n+\t\treturn false;\n+\n+\tmnt_ns = ei->ns;\n+\treturn current->nsproxy->mnt_ns->seq >= mnt_ns->seq;\n+}\n+\n struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,\n \t\t\t\t\tint flag)\n {\n@@ -1598,6 +1619,10 @@ static int do_loopback(struct path *path, const char *old_name,\n \tif (err)\n \t\treturn err;\n\n+\terr = -EINVAL;\n+\tif (mnt_ns_loop(&old_path))\n+\t\tgoto out;\n+\n \terr = lock_mount(path);\n \tif (err)\n \t\tgoto out;\n@@ -2204,6 +2229,15 @@ dput_out:\n \treturn retval;\n }\n\n+/*\n+ * Assign a sequence number so we can detect when we attempt to bind\n+ * mount a reference to an older mount namespace into the current\n+ * mount namespace, preventing reference counting loops.  A 64bit\n+ * number incrementing at 10Ghz will take 12,427 years to wrap which\n+ * is effectively never, so we can ignore the possibility.\n+ */\n+static atomic64_t mnt_ns_seq = ATOMIC64_INIT(1);\n+\n static struct mnt_namespace *alloc_mnt_ns(void)\n {\n \tstruct mnt_namespace *new_ns;\n@@ -2211,6 +2245,7 @@ static struct mnt_namespace *alloc_mnt_ns(void)\n \tnew_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL);\n \tif (!new_ns)\n \t\treturn ERR_PTR(-ENOMEM);\n+\tnew_ns->seq = atomic64_add_return(1, &mnt_ns_seq);\n \tatomic_set(&new_ns->count, 1);\n \tnew_ns->root = NULL;\n \tINIT_LIST_HEAD(&new_ns->list);\n@@ -2624,3 +2659,63 @@ bool our_mnt(struct vfsmount *mnt)\n {\n \treturn check_mnt(real_mount(mnt));\n }\n+\n+static void *mntns_get(struct task_struct *task)\n+{\n+\tstruct mnt_namespace *ns = NULL;\n+\tstruct nsproxy *nsproxy;\n+\n+\trcu_read_lock();\n+\tnsproxy = task_nsproxy(task);\n+\tif (nsproxy) {\n+\t\tns = nsproxy->mnt_ns;\n+\t\tget_mnt_ns(ns);\n+\t}\n+\trcu_read_unlock();\n+\n+\treturn ns;\n+}\n+\n+static void mntns_put(void *ns)\n+{\n+\tput_mnt_ns(ns);\n+}\n+\n+static int mntns_install(struct nsproxy *nsproxy, void *ns)\n+{\n+\tstruct fs_struct *fs = current->fs;\n+\tstruct mnt_namespace *mnt_ns = ns;\n+\tstruct path root;\n+\n+\tif (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_CHROOT))\n+\t\treturn -EINVAL;\n+\n+\tif (fs->users != 1)\n+\t\treturn -EINVAL;\n+\n+\tget_mnt_ns(mnt_ns);\n+\tput_mnt_ns(nsproxy->mnt_ns);\n+\tnsproxy->mnt_ns = mnt_ns;\n+\n+\t/* Find the root */\n+\troot.mnt    = &mnt_ns->root->mnt;\n+\troot.dentry = mnt_ns->root->mnt.mnt_root;\n+\tpath_get(&root);\n+\twhile(d_mountpoint(root.dentry) && follow_down_one(&root))\n+\t\t;\n+\n+\t/* Update the pwd and root */\n+\tset_fs_pwd(fs, &root);\n+\tset_fs_root(fs, &root);\n+\n+\tpath_put(&root);\n+\treturn 0;\n+}\n+\n+const struct proc_ns_operations mntns_operations = {\n+\t.name\t\t= \"mnt\",\n+\t.type\t\t= CLONE_NEWNS,\n+\t.get\t\t= mntns_get,\n+\t.put\t\t= mntns_put,\n+\t.install\t= mntns_install,\n+};\ndiff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c\nindex 0d9e23a..a971f8e 100644\n--- a/fs/proc/namespaces.c\n+++ b/fs/proc/namespaces.c\n@@ -24,6 +24,10 @@ static const struct proc_ns_operations *ns_entries[] = {\n #ifdef CONFIG_IPC_NS\n \t&ipcns_operations,\n #endif\n+#ifdef CONFIG_PID_NS\n+\t&pidns_operations,\n+#endif\n+\t&mntns_operations,\n };\n\n static const struct file_operations ns_file_operations = {\n@@ -198,3 +202,7 @@ out_invalid:\n \treturn ERR_PTR(-EINVAL);\n }\n\n+bool proc_ns_inode(struct inode *inode)\n+{\n+\treturn inode->i_fop == &ns_file_operations;\n+}\ndiff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h\nindex 85c5073..41913af 100644\n--- a/include/linux/proc_fs.h\n+++ b/include/linux/proc_fs.h\n@@ -174,6 +174,7 @@ extern struct proc_dir_entry *proc_net_mkdir(struct net *net, const char *name,\n \tstruct proc_dir_entry *parent);\n\n extern struct file *proc_ns_fget(int fd);\n+extern bool proc_ns_inode(struct inode *inode);\n\n #else\n\n@@ -229,6 +230,11 @@ static inline struct file *proc_ns_fget(int fd)\n \treturn ERR_PTR(-EINVAL);\n }\n\n+static inline bool proc_ns_inode(struct inode *inode)\n+{\n+\treturn false;\n+}\n+\n #endif /* CONFIG_PROC_FS */\n\n #if !defined(CONFIG_PROC_KCORE)\n@@ -251,6 +257,8 @@ struct proc_ns_operations {\n extern const struct proc_ns_operations netns_operations;\n extern const struct proc_ns_operations utsns_operations;\n extern const struct proc_ns_operations ipcns_operations;\n+extern const struct proc_ns_operations pidns_operations;\n+extern const struct proc_ns_operations mntns_operations;\n\n union proc_op {\n \tint (*proc_get_link)(struct dentry *, struct path *);\n--\n2.8.1","distinct":true,"url":"https://api.github.com/repos/robcore/Hulk-Kernel-V2/commits/b1e42b0ff9ebe98adb5c3950ce21e324e06022ae"},{"sha":"d4925437c215c963e56a88096fa7db9c64f3ba73","author":{"name":"robcore","email":"a3b05a675e90e628f2d9df6520db16da9bff1bff@gmail.com"},"message":"From 6f52736ca399e78f7012b6f716b3cbeaefaf084c Mon Sep 17 00:00:00 2001\nFrom: \"Eric W. Biederman\" <ebiederm@xmission.com>\nDate: Thu, 26 Jul 2012 21:08:32 -0700\nSubject: [PATCH 5970/6000] vfs: Add a user namespace reference from struct\n mnt_namespace\n\nThis will allow for support for unprivileged mounts in a new user namespace.\n\nAcked-by: \"Serge E. Hallyn\" <serge@hallyn.com>\nSigned-off-by: \"Eric W. Biederman\" <ebiederm@xmission.com>\n(cherry picked from commit 771b1371686e0a63e938ada28de020b9a0040f55)\n---\n fs/mount.h                    |  1 +\n fs/namespace.c                | 24 ++++++++++++++++--------\n include/linux/mnt_namespace.h |  3 ++-\n kernel/nsproxy.c              |  2 +-\n 4 files changed, 20 insertions(+), 10 deletions(-)\n\ndiff --git a/fs/mount.h b/fs/mount.h\nindex e9c37dd..630fafc 100644\n--- a/fs/mount.h\n+++ b/fs/mount.h\n@@ -6,6 +6,7 @@ struct mnt_namespace {\n \tatomic_t\t\tcount;\n \tstruct mount *\troot;\n \tstruct list_head\tlist;\n+\tstruct user_namespace\t*user_ns;\n \tu64\t\t\tseq;\t/* Sequence number to prevent loops */\n \twait_queue_head_t poll;\n \tint event;\ndiff --git a/fs/namespace.c b/fs/namespace.c\nindex c633e14..0de6953 100644\n--- a/fs/namespace.c\n+++ b/fs/namespace.c\n@@ -12,6 +12,7 @@\n #include <linux/export.h>\n #include <linux/capability.h>\n #include <linux/mnt_namespace.h>\n+#include <linux/user_namespace.h>\n #include <linux/namei.h>\n #include <linux/security.h>\n #include <linux/idr.h>\n@@ -2229,6 +2230,12 @@ dput_out:\n \treturn retval;\n }\n\n+static void free_mnt_ns(struct mnt_namespace *ns)\n+{\n+\tput_user_ns(ns->user_ns);\n+\tkfree(ns);\n+}\n+\n /*\n  * Assign a sequence number so we can detect when we attempt to bind\n  * mount a reference to an older mount namespace into the current\n@@ -2238,7 +2245,7 @@ dput_out:\n  */\n static atomic64_t mnt_ns_seq = ATOMIC64_INIT(1);\n\n-static struct mnt_namespace *alloc_mnt_ns(void)\n+static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns)\n {\n \tstruct mnt_namespace *new_ns;\n\n@@ -2251,6 +2258,7 @@ static struct mnt_namespace *alloc_mnt_ns(void)\n \tINIT_LIST_HEAD(&new_ns->list);\n \tinit_waitqueue_head(&new_ns->poll);\n \tnew_ns->event = 0;\n+\tnew_ns->user_ns = get_user_ns(user_ns);\n \treturn new_ns;\n }\n\n@@ -2259,7 +2267,7 @@ static struct mnt_namespace *alloc_mnt_ns(void)\n  * copied from the namespace of the passed in task structure.\n  */\n static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,\n-\t\tstruct fs_struct *fs)\n+\t\tstruct user_namespace *user_ns, struct fs_struct *fs)\n {\n \tstruct mnt_namespace *new_ns;\n \tstruct vfsmount *rootmnt = NULL, *pwdmnt = NULL;\n@@ -2267,7 +2275,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,\n \tstruct mount *old = mnt_ns->root;\n \tstruct mount *new;\n\n-\tnew_ns = alloc_mnt_ns();\n+\tnew_ns = alloc_mnt_ns(user_ns);\n \tif (IS_ERR(new_ns))\n \t\treturn new_ns;\n\n@@ -2276,7 +2284,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,\n \tnew = copy_tree(old, old->mnt.mnt_root, CL_COPY_ALL | CL_EXPIRE);\n \tif (IS_ERR(new)) {\n \t\tup_write(&namespace_sem);\n-\t\tkfree(new_ns);\n+\t\tfree_mnt_ns(new_ns);\n \t\treturn ERR_CAST(new);\n \t}\n \tnew_ns->root = new;\n@@ -2317,7 +2325,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,\n }\n\n struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,\n-\t\tstruct fs_struct *new_fs)\n+\t\tstruct user_namespace *user_ns, struct fs_struct *new_fs)\n {\n \tstruct mnt_namespace *new_ns;\n\n@@ -2327,7 +2335,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,\n \tif (!(flags & CLONE_NEWNS))\n \t\treturn ns;\n\n-\tnew_ns = dup_mnt_ns(ns, new_fs);\n+\tnew_ns = dup_mnt_ns(ns, user_ns, new_fs);\n\n \tput_mnt_ns(ns);\n \treturn new_ns;\n@@ -2339,7 +2347,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,\n  */\n static struct mnt_namespace *create_mnt_ns(struct vfsmount *m)\n {\n-\tstruct mnt_namespace *new_ns = alloc_mnt_ns();\n+\tstruct mnt_namespace *new_ns = alloc_mnt_ns(&init_user_ns);\n \tif (!IS_ERR(new_ns)) {\n \t\tstruct mount *mnt = real_mount(m);\n \t\tmnt->mnt_ns = new_ns;\n@@ -2625,7 +2633,7 @@ void put_mnt_ns(struct mnt_namespace *ns)\n \tbr_write_unlock(&vfsmount_lock);\n \tup_write(&namespace_sem);\n \trelease_mounts(&umount_list);\n-\tkfree(ns);\n+\tfree_mnt_ns(ns);\n }\n\n struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)\ndiff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h\nindex 5a8e390..12b2ab5 100644\n--- a/include/linux/mnt_namespace.h\n+++ b/include/linux/mnt_namespace.h\n@@ -4,9 +4,10 @@\n\n struct mnt_namespace;\n struct fs_struct;\n+struct user_namespace;\n\n extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,\n-\t\tstruct fs_struct *);\n+\t\tstruct user_namespace *, struct fs_struct *);\n extern void put_mnt_ns(struct mnt_namespace *ns);\n\n extern const struct file_operations proc_mounts_operations;\ndiff --git a/kernel/nsproxy.c b/kernel/nsproxy.c\nindex b576f7f..5b6ce19 100644\n--- a/kernel/nsproxy.c\n+++ b/kernel/nsproxy.c\n@@ -66,7 +66,7 @@ static struct nsproxy *create_new_namespaces(unsigned long flags,\n \tif (!new_nsp)\n \t\treturn ERR_PTR(-ENOMEM);\n\n-\tnew_nsp->mnt_ns = copy_mnt_ns(flags, tsk->nsproxy->mnt_ns, new_fs);\n+\tnew_nsp->mnt_ns = copy_mnt_ns(flags, tsk->nsproxy->mnt_ns, task_cred_xxx(tsk, user_ns), new_fs);\n \tif (IS_ERR(new_nsp->mnt_ns)) {\n \t\terr = PTR_ERR(new_nsp->mnt_ns);\n \t\tgoto out_ns;\n--\n2.8.1","distinct":true,"url":"https://api.github.com/repos/robcore/Hulk-Kernel-V2/commits/d4925437c215c963e56a88096fa7db9c64f3ba73"},{"sha":"3ef7f3fe840357aab02a815e2d903497ad5dffcb","author":{"name":"robcore","email":"a3b05a675e90e628f2d9df6520db16da9bff1bff@gmail.com"},"message":"allow unpriveliged manipulation of mount namespace","distinct":true,"url":"https://api.github.com/repos/robcore/Hulk-Kernel-V2/commits/3ef7f3fe840357aab02a815e2d903497ad5dffcb"}]}
{"actor":{"display_login":"robcore"}}