aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namespace.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namespace.c')
-rw-r--r--fs/namespace.c95
1 files changed, 95 insertions, 0 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index 24960626bb6b..d287e7e74644 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -20,6 +20,7 @@
20#include <linux/fs_struct.h> /* get_fs_root et.al. */ 20#include <linux/fs_struct.h> /* get_fs_root et.al. */
21#include <linux/fsnotify.h> /* fsnotify_vfsmount_delete */ 21#include <linux/fsnotify.h> /* fsnotify_vfsmount_delete */
22#include <linux/uaccess.h> 22#include <linux/uaccess.h>
23#include <linux/proc_fs.h>
23#include "pnode.h" 24#include "pnode.h"
24#include "internal.h" 25#include "internal.h"
25 26
@@ -1308,6 +1309,26 @@ static int mount_is_safe(struct path *path)
1308#endif 1309#endif
1309} 1310}
1310 1311
1312static bool mnt_ns_loop(struct path *path)
1313{
1314 /* Could bind mounting the mount namespace inode cause a
1315 * mount namespace loop?
1316 */
1317 struct inode *inode = path->dentry->d_inode;
1318 struct proc_inode *ei;
1319 struct mnt_namespace *mnt_ns;
1320
1321 if (!proc_ns_inode(inode))
1322 return false;
1323
1324 ei = PROC_I(inode);
1325 if (ei->ns_ops != &mntns_operations)
1326 return false;
1327
1328 mnt_ns = ei->ns;
1329 return current->nsproxy->mnt_ns->seq >= mnt_ns->seq;
1330}
1331
1311struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, 1332struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
1312 int flag) 1333 int flag)
1313{ 1334{
@@ -1655,6 +1676,10 @@ static int do_loopback(struct path *path, const char *old_name,
1655 if (err) 1676 if (err)
1656 return err; 1677 return err;
1657 1678
1679 err = -EINVAL;
1680 if (mnt_ns_loop(&old_path))
1681 goto out;
1682
1658 err = lock_mount(path); 1683 err = lock_mount(path);
1659 if (err) 1684 if (err)
1660 goto out; 1685 goto out;
@@ -2261,6 +2286,15 @@ dput_out:
2261 return retval; 2286 return retval;
2262} 2287}
2263 2288
2289/*
2290 * Assign a sequence number so we can detect when we attempt to bind
2291 * mount a reference to an older mount namespace into the current
2292 * mount namespace, preventing reference counting loops. A 64bit
2293 * number incrementing at 10Ghz will take 12,427 years to wrap which
2294 * is effectively never, so we can ignore the possibility.
2295 */
2296static atomic64_t mnt_ns_seq = ATOMIC64_INIT(1);
2297
2264static struct mnt_namespace *alloc_mnt_ns(void) 2298static struct mnt_namespace *alloc_mnt_ns(void)
2265{ 2299{
2266 struct mnt_namespace *new_ns; 2300 struct mnt_namespace *new_ns;
@@ -2268,6 +2302,7 @@ static struct mnt_namespace *alloc_mnt_ns(void)
2268 new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL); 2302 new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL);
2269 if (!new_ns) 2303 if (!new_ns)
2270 return ERR_PTR(-ENOMEM); 2304 return ERR_PTR(-ENOMEM);
2305 new_ns->seq = atomic64_add_return(1, &mnt_ns_seq);
2271 atomic_set(&new_ns->count, 1); 2306 atomic_set(&new_ns->count, 1);
2272 new_ns->root = NULL; 2307 new_ns->root = NULL;
2273 INIT_LIST_HEAD(&new_ns->list); 2308 INIT_LIST_HEAD(&new_ns->list);
@@ -2681,3 +2716,63 @@ bool our_mnt(struct vfsmount *mnt)
2681{ 2716{
2682 return check_mnt(real_mount(mnt)); 2717 return check_mnt(real_mount(mnt));
2683} 2718}
2719
2720static void *mntns_get(struct task_struct *task)
2721{
2722 struct mnt_namespace *ns = NULL;
2723 struct nsproxy *nsproxy;
2724
2725 rcu_read_lock();
2726 nsproxy = task_nsproxy(task);
2727 if (nsproxy) {
2728 ns = nsproxy->mnt_ns;
2729 get_mnt_ns(ns);
2730 }
2731 rcu_read_unlock();
2732
2733 return ns;
2734}
2735
2736static void mntns_put(void *ns)
2737{
2738 put_mnt_ns(ns);
2739}
2740
2741static int mntns_install(struct nsproxy *nsproxy, void *ns)
2742{
2743 struct fs_struct *fs = current->fs;
2744 struct mnt_namespace *mnt_ns = ns;
2745 struct path root;
2746
2747 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_CHROOT))
2748 return -EINVAL;
2749
2750 if (fs->users != 1)
2751 return -EINVAL;
2752
2753 get_mnt_ns(mnt_ns);
2754 put_mnt_ns(nsproxy->mnt_ns);
2755 nsproxy->mnt_ns = mnt_ns;
2756
2757 /* Find the root */
2758 root.mnt = &mnt_ns->root->mnt;
2759 root.dentry = mnt_ns->root->mnt.mnt_root;
2760 path_get(&root);
2761 while(d_mountpoint(root.dentry) && follow_down_one(&root))
2762 ;
2763
2764 /* Update the pwd and root */
2765 set_fs_pwd(fs, &root);
2766 set_fs_root(fs, &root);
2767
2768 path_put(&root);
2769 return 0;
2770}
2771
2772const struct proc_ns_operations mntns_operations = {
2773 .name = "mnt",
2774 .type = CLONE_NEWNS,
2775 .get = mntns_get,
2776 .put = mntns_put,
2777 .install = mntns_install,
2778};