aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-16 18:53:03 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-16 18:53:03 -0500
commit603ba7e41bf5d405aba22294af5d075d8898176d (patch)
treefb9cf0b7c4912b5105f7da5efdd204cd0e66c8db /fs
parent31f48fc8f226f968d6e6b9b9718abe8e16c51fe8 (diff)
parent93fe74b2e2b5d266d630f0c3f8287efcbe6ecd10 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs pile #2 from Al Viro: "Next pile (and there'll be one or two more). The large piece in this one is getting rid of /proc/*/ns/* weirdness; among other things, it allows to (finally) make nameidata completely opaque outside of fs/namei.c, making for easier further cleanups in there" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: coda_venus_readdir(): use file_inode() fs/namei.c: fold link_path_walk() call into path_init() path_init(): don't bother with LOOKUP_PARENT in argument fs/namei.c: new helper (path_cleanup()) path_init(): store the "base" pointer to file in nameidata itself make default ->i_fop have ->open() fail with ENXIO make nameidata completely opaque outside of fs/namei.c kill proc_ns completely take the targets of /proc/*/ns/* symlinks to separate fs bury struct proc_ns in fs/proc copy address of proc_ns_ops into ns_common new helpers: ns_alloc_inum/ns_free_inum make proc_ns_operations work with struct ns_common * instead of void * switch the rest of proc_ns_operations to working with &...->ns netns: switch ->get()/->put()/->install()/->inum() to working with &net->ns make mntns ->get()/->put()/->install()/->inum() work with &mnt_ns->ns common object embedded into various struct ....ns
Diffstat (limited to 'fs')
-rw-r--r--fs/Makefile2
-rw-r--r--fs/coda/dir.c4
-rw-r--r--fs/inode.c11
-rw-r--r--fs/internal.h5
-rw-r--r--fs/mount.h3
-rw-r--r--fs/namei.c98
-rw-r--r--fs/namespace.c51
-rw-r--r--fs/nsfs.c161
-rw-r--r--fs/proc/inode.c10
-rw-r--r--fs/proc/internal.h2
-rw-r--r--fs/proc/namespaces.c153
11 files changed, 267 insertions, 233 deletions
diff --git a/fs/Makefile b/fs/Makefile
index da0bbb456d3f..bedff48e8fdc 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -11,7 +11,7 @@ obj-y := open.o read_write.o file_table.o super.o \
11 attr.o bad_inode.o file.o filesystems.o namespace.o \ 11 attr.o bad_inode.o file.o filesystems.o namespace.o \
12 seq_file.o xattr.o libfs.o fs-writeback.o \ 12 seq_file.o xattr.o libfs.o fs-writeback.o \
13 pnode.o splice.o sync.o utimes.o \ 13 pnode.o splice.o sync.o utimes.o \
14 stack.o fs_struct.o statfs.o fs_pin.o 14 stack.o fs_struct.o statfs.o fs_pin.o nsfs.o
15 15
16ifeq ($(CONFIG_BLOCK),y) 16ifeq ($(CONFIG_BLOCK),y)
17obj-y += buffer.o block_dev.o direct-io.o mpage.o 17obj-y += buffer.o block_dev.o direct-io.o mpage.o
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 7ff025966e4f..86c893884eb9 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -426,7 +426,6 @@ static int coda_venus_readdir(struct file *coda_file, struct dir_context *ctx)
426 struct coda_file_info *cfi; 426 struct coda_file_info *cfi;
427 struct coda_inode_info *cii; 427 struct coda_inode_info *cii;
428 struct file *host_file; 428 struct file *host_file;
429 struct dentry *de;
430 struct venus_dirent *vdir; 429 struct venus_dirent *vdir;
431 unsigned long vdir_size = offsetof(struct venus_dirent, d_name); 430 unsigned long vdir_size = offsetof(struct venus_dirent, d_name);
432 unsigned int type; 431 unsigned int type;
@@ -438,8 +437,7 @@ static int coda_venus_readdir(struct file *coda_file, struct dir_context *ctx)
438 BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC); 437 BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
439 host_file = cfi->cfi_container; 438 host_file = cfi->cfi_container;
440 439
441 de = coda_file->f_path.dentry; 440 cii = ITOC(file_inode(coda_file));
442 cii = ITOC(de->d_inode);
443 441
444 vdir = kmalloc(sizeof(*vdir), GFP_KERNEL); 442 vdir = kmalloc(sizeof(*vdir), GFP_KERNEL);
445 if (!vdir) return -ENOMEM; 443 if (!vdir) return -ENOMEM;
diff --git a/fs/inode.c b/fs/inode.c
index ad60555b4768..aa149e7262ac 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -114,6 +114,11 @@ int proc_nr_inodes(struct ctl_table *table, int write,
114} 114}
115#endif 115#endif
116 116
117static int no_open(struct inode *inode, struct file *file)
118{
119 return -ENXIO;
120}
121
117/** 122/**
118 * inode_init_always - perform inode structure intialisation 123 * inode_init_always - perform inode structure intialisation
119 * @sb: superblock inode belongs to 124 * @sb: superblock inode belongs to
@@ -125,7 +130,7 @@ int proc_nr_inodes(struct ctl_table *table, int write,
125int inode_init_always(struct super_block *sb, struct inode *inode) 130int inode_init_always(struct super_block *sb, struct inode *inode)
126{ 131{
127 static const struct inode_operations empty_iops; 132 static const struct inode_operations empty_iops;
128 static const struct file_operations empty_fops; 133 static const struct file_operations no_open_fops = {.open = no_open};
129 struct address_space *const mapping = &inode->i_data; 134 struct address_space *const mapping = &inode->i_data;
130 135
131 inode->i_sb = sb; 136 inode->i_sb = sb;
@@ -133,7 +138,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
133 inode->i_flags = 0; 138 inode->i_flags = 0;
134 atomic_set(&inode->i_count, 1); 139 atomic_set(&inode->i_count, 1);
135 inode->i_op = &empty_iops; 140 inode->i_op = &empty_iops;
136 inode->i_fop = &empty_fops; 141 inode->i_fop = &no_open_fops;
137 inode->__i_nlink = 1; 142 inode->__i_nlink = 1;
138 inode->i_opflags = 0; 143 inode->i_opflags = 0;
139 i_uid_write(inode, 0); 144 i_uid_write(inode, 0);
@@ -1798,7 +1803,7 @@ void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev)
1798 } else if (S_ISFIFO(mode)) 1803 } else if (S_ISFIFO(mode))
1799 inode->i_fop = &pipefifo_fops; 1804 inode->i_fop = &pipefifo_fops;
1800 else if (S_ISSOCK(mode)) 1805 else if (S_ISSOCK(mode))
1801 inode->i_fop = &bad_sock_fops; 1806 ; /* leave it no_open_fops */
1802 else 1807 else
1803 printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o) for" 1808 printk(KERN_DEBUG "init_special_inode: bogus i_mode (%o) for"
1804 " inode %s:%lu\n", mode, inode->i_sb->s_id, 1809 " inode %s:%lu\n", mode, inode->i_sb->s_id,
diff --git a/fs/internal.h b/fs/internal.h
index 757ba2abf21e..e9a61fe67575 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -147,3 +147,8 @@ extern const struct file_operations pipefifo_fops;
147 */ 147 */
148extern void sb_pin_kill(struct super_block *sb); 148extern void sb_pin_kill(struct super_block *sb);
149extern void mnt_pin_kill(struct mount *m); 149extern void mnt_pin_kill(struct mount *m);
150
151/*
152 * fs/nsfs.c
153 */
154extern struct dentry_operations ns_dentry_operations;
diff --git a/fs/mount.h b/fs/mount.h
index f82c62840905..0ad6f760ce52 100644
--- a/fs/mount.h
+++ b/fs/mount.h
@@ -1,10 +1,11 @@
1#include <linux/mount.h> 1#include <linux/mount.h>
2#include <linux/seq_file.h> 2#include <linux/seq_file.h>
3#include <linux/poll.h> 3#include <linux/poll.h>
4#include <linux/ns_common.h>
4 5
5struct mnt_namespace { 6struct mnt_namespace {
6 atomic_t count; 7 atomic_t count;
7 unsigned int proc_inum; 8 struct ns_common ns;
8 struct mount * root; 9 struct mount * root;
9 struct list_head list; 10 struct list_head list;
10 struct user_namespace *user_ns; 11 struct user_namespace *user_ns;
diff --git a/fs/namei.c b/fs/namei.c
index ca814165d84c..bc35b02883bb 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -487,6 +487,19 @@ void path_put(const struct path *path)
487} 487}
488EXPORT_SYMBOL(path_put); 488EXPORT_SYMBOL(path_put);
489 489
490struct nameidata {
491 struct path path;
492 struct qstr last;
493 struct path root;
494 struct inode *inode; /* path.dentry.d_inode */
495 unsigned int flags;
496 unsigned seq, m_seq;
497 int last_type;
498 unsigned depth;
499 struct file *base;
500 char *saved_names[MAX_NESTED_LINKS + 1];
501};
502
490/* 503/*
491 * Path walking has 2 modes, rcu-walk and ref-walk (see 504 * Path walking has 2 modes, rcu-walk and ref-walk (see
492 * Documentation/filesystems/path-lookup.txt). In situations when we can't 505 * Documentation/filesystems/path-lookup.txt). In situations when we can't
@@ -695,6 +708,18 @@ void nd_jump_link(struct nameidata *nd, struct path *path)
695 nd->flags |= LOOKUP_JUMPED; 708 nd->flags |= LOOKUP_JUMPED;
696} 709}
697 710
711void nd_set_link(struct nameidata *nd, char *path)
712{
713 nd->saved_names[nd->depth] = path;
714}
715EXPORT_SYMBOL(nd_set_link);
716
717char *nd_get_link(struct nameidata *nd)
718{
719 return nd->saved_names[nd->depth];
720}
721EXPORT_SYMBOL(nd_get_link);
722
698static inline void put_link(struct nameidata *nd, struct path *link, void *cookie) 723static inline void put_link(struct nameidata *nd, struct path *link, void *cookie)
699{ 724{
700 struct inode *inode = link->dentry->d_inode; 725 struct inode *inode = link->dentry->d_inode;
@@ -1821,13 +1846,14 @@ static int link_path_walk(const char *name, struct nameidata *nd)
1821} 1846}
1822 1847
1823static int path_init(int dfd, const char *name, unsigned int flags, 1848static int path_init(int dfd, const char *name, unsigned int flags,
1824 struct nameidata *nd, struct file **fp) 1849 struct nameidata *nd)
1825{ 1850{
1826 int retval = 0; 1851 int retval = 0;
1827 1852
1828 nd->last_type = LAST_ROOT; /* if there are only slashes... */ 1853 nd->last_type = LAST_ROOT; /* if there are only slashes... */
1829 nd->flags = flags | LOOKUP_JUMPED; 1854 nd->flags = flags | LOOKUP_JUMPED | LOOKUP_PARENT;
1830 nd->depth = 0; 1855 nd->depth = 0;
1856 nd->base = NULL;
1831 if (flags & LOOKUP_ROOT) { 1857 if (flags & LOOKUP_ROOT) {
1832 struct dentry *root = nd->root.dentry; 1858 struct dentry *root = nd->root.dentry;
1833 struct inode *inode = root->d_inode; 1859 struct inode *inode = root->d_inode;
@@ -1847,7 +1873,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
1847 } else { 1873 } else {
1848 path_get(&nd->path); 1874 path_get(&nd->path);
1849 } 1875 }
1850 return 0; 1876 goto done;
1851 } 1877 }
1852 1878
1853 nd->root.mnt = NULL; 1879 nd->root.mnt = NULL;
@@ -1897,7 +1923,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
1897 nd->path = f.file->f_path; 1923 nd->path = f.file->f_path;
1898 if (flags & LOOKUP_RCU) { 1924 if (flags & LOOKUP_RCU) {
1899 if (f.flags & FDPUT_FPUT) 1925 if (f.flags & FDPUT_FPUT)
1900 *fp = f.file; 1926 nd->base = f.file;
1901 nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); 1927 nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
1902 rcu_read_lock(); 1928 rcu_read_lock();
1903 } else { 1929 } else {
@@ -1908,13 +1934,26 @@ static int path_init(int dfd, const char *name, unsigned int flags,
1908 1934
1909 nd->inode = nd->path.dentry->d_inode; 1935 nd->inode = nd->path.dentry->d_inode;
1910 if (!(flags & LOOKUP_RCU)) 1936 if (!(flags & LOOKUP_RCU))
1911 return 0; 1937 goto done;
1912 if (likely(!read_seqcount_retry(&nd->path.dentry->d_seq, nd->seq))) 1938 if (likely(!read_seqcount_retry(&nd->path.dentry->d_seq, nd->seq)))
1913 return 0; 1939 goto done;
1914 if (!(nd->flags & LOOKUP_ROOT)) 1940 if (!(nd->flags & LOOKUP_ROOT))
1915 nd->root.mnt = NULL; 1941 nd->root.mnt = NULL;
1916 rcu_read_unlock(); 1942 rcu_read_unlock();
1917 return -ECHILD; 1943 return -ECHILD;
1944done:
1945 current->total_link_count = 0;
1946 return link_path_walk(name, nd);
1947}
1948
1949static void path_cleanup(struct nameidata *nd)
1950{
1951 if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT)) {
1952 path_put(&nd->root);
1953 nd->root.mnt = NULL;
1954 }
1955 if (unlikely(nd->base))
1956 fput(nd->base);
1918} 1957}
1919 1958
1920static inline int lookup_last(struct nameidata *nd, struct path *path) 1959static inline int lookup_last(struct nameidata *nd, struct path *path)
@@ -1930,7 +1969,6 @@ static inline int lookup_last(struct nameidata *nd, struct path *path)
1930static int path_lookupat(int dfd, const char *name, 1969static int path_lookupat(int dfd, const char *name,
1931 unsigned int flags, struct nameidata *nd) 1970 unsigned int flags, struct nameidata *nd)
1932{ 1971{
1933 struct file *base = NULL;
1934 struct path path; 1972 struct path path;
1935 int err; 1973 int err;
1936 1974
@@ -1948,14 +1986,7 @@ static int path_lookupat(int dfd, const char *name,
1948 * be handled by restarting a traditional ref-walk (which will always 1986 * be handled by restarting a traditional ref-walk (which will always
1949 * be able to complete). 1987 * be able to complete).
1950 */ 1988 */
1951 err = path_init(dfd, name, flags | LOOKUP_PARENT, nd, &base); 1989 err = path_init(dfd, name, flags, nd);
1952
1953 if (unlikely(err))
1954 goto out;
1955
1956 current->total_link_count = 0;
1957 err = link_path_walk(name, nd);
1958
1959 if (!err && !(flags & LOOKUP_PARENT)) { 1990 if (!err && !(flags & LOOKUP_PARENT)) {
1960 err = lookup_last(nd, &path); 1991 err = lookup_last(nd, &path);
1961 while (err > 0) { 1992 while (err > 0) {
@@ -1983,14 +2014,7 @@ static int path_lookupat(int dfd, const char *name,
1983 } 2014 }
1984 } 2015 }
1985 2016
1986out: 2017 path_cleanup(nd);
1987 if (base)
1988 fput(base);
1989
1990 if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT)) {
1991 path_put(&nd->root);
1992 nd->root.mnt = NULL;
1993 }
1994 return err; 2018 return err;
1995} 2019}
1996 2020
@@ -2297,19 +2321,13 @@ out:
2297static int 2321static int
2298path_mountpoint(int dfd, const char *name, struct path *path, unsigned int flags) 2322path_mountpoint(int dfd, const char *name, struct path *path, unsigned int flags)
2299{ 2323{
2300 struct file *base = NULL;
2301 struct nameidata nd; 2324 struct nameidata nd;
2302 int err; 2325 int err;
2303 2326
2304 err = path_init(dfd, name, flags | LOOKUP_PARENT, &nd, &base); 2327 err = path_init(dfd, name, flags, &nd);
2305 if (unlikely(err)) 2328 if (unlikely(err))
2306 goto out; 2329 goto out;
2307 2330
2308 current->total_link_count = 0;
2309 err = link_path_walk(name, &nd);
2310 if (err)
2311 goto out;
2312
2313 err = mountpoint_last(&nd, path); 2331 err = mountpoint_last(&nd, path);
2314 while (err > 0) { 2332 while (err > 0) {
2315 void *cookie; 2333 void *cookie;
@@ -2325,12 +2343,7 @@ path_mountpoint(int dfd, const char *name, struct path *path, unsigned int flags
2325 put_link(&nd, &link, cookie); 2343 put_link(&nd, &link, cookie);
2326 } 2344 }
2327out: 2345out:
2328 if (base) 2346 path_cleanup(&nd);
2329 fput(base);
2330
2331 if (nd.root.mnt && !(nd.flags & LOOKUP_ROOT))
2332 path_put(&nd.root);
2333
2334 return err; 2347 return err;
2335} 2348}
2336 2349
@@ -3181,7 +3194,6 @@ out:
3181static struct file *path_openat(int dfd, struct filename *pathname, 3194static struct file *path_openat(int dfd, struct filename *pathname,
3182 struct nameidata *nd, const struct open_flags *op, int flags) 3195 struct nameidata *nd, const struct open_flags *op, int flags)
3183{ 3196{
3184 struct file *base = NULL;
3185 struct file *file; 3197 struct file *file;
3186 struct path path; 3198 struct path path;
3187 int opened = 0; 3199 int opened = 0;
@@ -3198,12 +3210,7 @@ static struct file *path_openat(int dfd, struct filename *pathname,
3198 goto out; 3210 goto out;
3199 } 3211 }
3200 3212
3201 error = path_init(dfd, pathname->name, flags | LOOKUP_PARENT, nd, &base); 3213 error = path_init(dfd, pathname->name, flags, nd);
3202 if (unlikely(error))
3203 goto out;
3204
3205 current->total_link_count = 0;
3206 error = link_path_walk(pathname->name, nd);
3207 if (unlikely(error)) 3214 if (unlikely(error))
3208 goto out; 3215 goto out;
3209 3216
@@ -3229,10 +3236,7 @@ static struct file *path_openat(int dfd, struct filename *pathname,
3229 put_link(nd, &link, cookie); 3236 put_link(nd, &link, cookie);
3230 } 3237 }
3231out: 3238out:
3232 if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT)) 3239 path_cleanup(nd);
3233 path_put(&nd->root);
3234 if (base)
3235 fput(base);
3236 if (!(opened & FILE_OPENED)) { 3240 if (!(opened & FILE_OPENED)) {
3237 BUG_ON(!error); 3241 BUG_ON(!error);
3238 put_filp(file); 3242 put_filp(file);
diff --git a/fs/namespace.c b/fs/namespace.c
index 5b66b2b3624d..30df6e7dd807 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1569,17 +1569,13 @@ SYSCALL_DEFINE1(oldumount, char __user *, name)
1569static bool is_mnt_ns_file(struct dentry *dentry) 1569static bool is_mnt_ns_file(struct dentry *dentry)
1570{ 1570{
1571 /* Is this a proxy for a mount namespace? */ 1571 /* Is this a proxy for a mount namespace? */
1572 struct inode *inode = dentry->d_inode; 1572 return dentry->d_op == &ns_dentry_operations &&
1573 struct proc_ns *ei; 1573 dentry->d_fsdata == &mntns_operations;
1574 1574}
1575 if (!proc_ns_inode(inode))
1576 return false;
1577
1578 ei = get_proc_ns(inode);
1579 if (ei->ns_ops != &mntns_operations)
1580 return false;
1581 1575
1582 return true; 1576struct mnt_namespace *to_mnt_ns(struct ns_common *ns)
1577{
1578 return container_of(ns, struct mnt_namespace, ns);
1583} 1579}
1584 1580
1585static bool mnt_ns_loop(struct dentry *dentry) 1581static bool mnt_ns_loop(struct dentry *dentry)
@@ -1591,7 +1587,7 @@ static bool mnt_ns_loop(struct dentry *dentry)
1591 if (!is_mnt_ns_file(dentry)) 1587 if (!is_mnt_ns_file(dentry))
1592 return false; 1588 return false;
1593 1589
1594 mnt_ns = get_proc_ns(dentry->d_inode)->ns; 1590 mnt_ns = to_mnt_ns(get_proc_ns(dentry->d_inode));
1595 return current->nsproxy->mnt_ns->seq >= mnt_ns->seq; 1591 return current->nsproxy->mnt_ns->seq >= mnt_ns->seq;
1596} 1592}
1597 1593
@@ -2020,7 +2016,10 @@ static int do_loopback(struct path *path, const char *old_name,
2020 if (IS_MNT_UNBINDABLE(old)) 2016 if (IS_MNT_UNBINDABLE(old))
2021 goto out2; 2017 goto out2;
2022 2018
2023 if (!check_mnt(parent) || !check_mnt(old)) 2019 if (!check_mnt(parent))
2020 goto out2;
2021
2022 if (!check_mnt(old) && old_path.dentry->d_op != &ns_dentry_operations)
2024 goto out2; 2023 goto out2;
2025 2024
2026 if (!recurse && has_locked_children(old, old_path.dentry)) 2025 if (!recurse && has_locked_children(old, old_path.dentry))
@@ -2640,7 +2639,7 @@ dput_out:
2640 2639
2641static void free_mnt_ns(struct mnt_namespace *ns) 2640static void free_mnt_ns(struct mnt_namespace *ns)
2642{ 2641{
2643 proc_free_inum(ns->proc_inum); 2642 ns_free_inum(&ns->ns);
2644 put_user_ns(ns->user_ns); 2643 put_user_ns(ns->user_ns);
2645 kfree(ns); 2644 kfree(ns);
2646} 2645}
@@ -2662,11 +2661,12 @@ static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns)
2662 new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL); 2661 new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL);
2663 if (!new_ns) 2662 if (!new_ns)
2664 return ERR_PTR(-ENOMEM); 2663 return ERR_PTR(-ENOMEM);
2665 ret = proc_alloc_inum(&new_ns->proc_inum); 2664 ret = ns_alloc_inum(&new_ns->ns);
2666 if (ret) { 2665 if (ret) {
2667 kfree(new_ns); 2666 kfree(new_ns);
2668 return ERR_PTR(ret); 2667 return ERR_PTR(ret);
2669 } 2668 }
2669 new_ns->ns.ops = &mntns_operations;
2670 new_ns->seq = atomic64_add_return(1, &mnt_ns_seq); 2670 new_ns->seq = atomic64_add_return(1, &mnt_ns_seq);
2671 atomic_set(&new_ns->count, 1); 2671 atomic_set(&new_ns->count, 1);
2672 new_ns->root = NULL; 2672 new_ns->root = NULL;
@@ -3144,31 +3144,31 @@ found:
3144 return visible; 3144 return visible;
3145} 3145}
3146 3146
3147static void *mntns_get(struct task_struct *task) 3147static struct ns_common *mntns_get(struct task_struct *task)
3148{ 3148{
3149 struct mnt_namespace *ns = NULL; 3149 struct ns_common *ns = NULL;
3150 struct nsproxy *nsproxy; 3150 struct nsproxy *nsproxy;
3151 3151
3152 task_lock(task); 3152 task_lock(task);
3153 nsproxy = task->nsproxy; 3153 nsproxy = task->nsproxy;
3154 if (nsproxy) { 3154 if (nsproxy) {
3155 ns = nsproxy->mnt_ns; 3155 ns = &nsproxy->mnt_ns->ns;
3156 get_mnt_ns(ns); 3156 get_mnt_ns(to_mnt_ns(ns));
3157 } 3157 }
3158 task_unlock(task); 3158 task_unlock(task);
3159 3159
3160 return ns; 3160 return ns;
3161} 3161}
3162 3162
3163static void mntns_put(void *ns) 3163static void mntns_put(struct ns_common *ns)
3164{ 3164{
3165 put_mnt_ns(ns); 3165 put_mnt_ns(to_mnt_ns(ns));
3166} 3166}
3167 3167
3168static int mntns_install(struct nsproxy *nsproxy, void *ns) 3168static int mntns_install(struct nsproxy *nsproxy, struct ns_common *ns)
3169{ 3169{
3170 struct fs_struct *fs = current->fs; 3170 struct fs_struct *fs = current->fs;
3171 struct mnt_namespace *mnt_ns = ns; 3171 struct mnt_namespace *mnt_ns = to_mnt_ns(ns);
3172 struct path root; 3172 struct path root;
3173 3173
3174 if (!ns_capable(mnt_ns->user_ns, CAP_SYS_ADMIN) || 3174 if (!ns_capable(mnt_ns->user_ns, CAP_SYS_ADMIN) ||
@@ -3198,17 +3198,10 @@ static int mntns_install(struct nsproxy *nsproxy, void *ns)
3198 return 0; 3198 return 0;
3199} 3199}
3200 3200
3201static unsigned int mntns_inum(void *ns)
3202{
3203 struct mnt_namespace *mnt_ns = ns;
3204 return mnt_ns->proc_inum;
3205}
3206
3207const struct proc_ns_operations mntns_operations = { 3201const struct proc_ns_operations mntns_operations = {
3208 .name = "mnt", 3202 .name = "mnt",
3209 .type = CLONE_NEWNS, 3203 .type = CLONE_NEWNS,
3210 .get = mntns_get, 3204 .get = mntns_get,
3211 .put = mntns_put, 3205 .put = mntns_put,
3212 .install = mntns_install, 3206 .install = mntns_install,
3213 .inum = mntns_inum,
3214}; 3207};
diff --git a/fs/nsfs.c b/fs/nsfs.c
new file mode 100644
index 000000000000..af1b24fa899d
--- /dev/null
+++ b/fs/nsfs.c
@@ -0,0 +1,161 @@
1#include <linux/mount.h>
2#include <linux/file.h>
3#include <linux/fs.h>
4#include <linux/proc_ns.h>
5#include <linux/magic.h>
6#include <linux/ktime.h>
7
8static struct vfsmount *nsfs_mnt;
9
10static const struct file_operations ns_file_operations = {
11 .llseek = no_llseek,
12};
13
14static char *ns_dname(struct dentry *dentry, char *buffer, int buflen)
15{
16 struct inode *inode = dentry->d_inode;
17 const struct proc_ns_operations *ns_ops = dentry->d_fsdata;
18
19 return dynamic_dname(dentry, buffer, buflen, "%s:[%lu]",
20 ns_ops->name, inode->i_ino);
21}
22
23static void ns_prune_dentry(struct dentry *dentry)
24{
25 struct inode *inode = dentry->d_inode;
26 if (inode) {
27 struct ns_common *ns = inode->i_private;
28 atomic_long_set(&ns->stashed, 0);
29 }
30}
31
32const struct dentry_operations ns_dentry_operations =
33{
34 .d_prune = ns_prune_dentry,
35 .d_delete = always_delete_dentry,
36 .d_dname = ns_dname,
37};
38
39static void nsfs_evict(struct inode *inode)
40{
41 struct ns_common *ns = inode->i_private;
42 clear_inode(inode);
43 ns->ops->put(ns);
44}
45
46void *ns_get_path(struct path *path, struct task_struct *task,
47 const struct proc_ns_operations *ns_ops)
48{
49 struct vfsmount *mnt = mntget(nsfs_mnt);
50 struct qstr qname = { .name = "", };
51 struct dentry *dentry;
52 struct inode *inode;
53 struct ns_common *ns;
54 unsigned long d;
55
56again:
57 ns = ns_ops->get(task);
58 if (!ns) {
59 mntput(mnt);
60 return ERR_PTR(-ENOENT);
61 }
62 rcu_read_lock();
63 d = atomic_long_read(&ns->stashed);
64 if (!d)
65 goto slow;
66 dentry = (struct dentry *)d;
67 if (!lockref_get_not_dead(&dentry->d_lockref))
68 goto slow;
69 rcu_read_unlock();
70 ns_ops->put(ns);
71got_it:
72 path->mnt = mnt;
73 path->dentry = dentry;
74 return NULL;
75slow:
76 rcu_read_unlock();
77 inode = new_inode_pseudo(mnt->mnt_sb);
78 if (!inode) {
79 ns_ops->put(ns);
80 mntput(mnt);
81 return ERR_PTR(-ENOMEM);
82 }
83 inode->i_ino = ns->inum;
84 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
85 inode->i_flags |= S_IMMUTABLE;
86 inode->i_mode = S_IFREG | S_IRUGO;
87 inode->i_fop = &ns_file_operations;
88 inode->i_private = ns;
89
90 dentry = d_alloc_pseudo(mnt->mnt_sb, &qname);
91 if (!dentry) {
92 iput(inode);
93 mntput(mnt);
94 return ERR_PTR(-ENOMEM);
95 }
96 d_instantiate(dentry, inode);
97 dentry->d_fsdata = (void *)ns_ops;
98 d = atomic_long_cmpxchg(&ns->stashed, 0, (unsigned long)dentry);
99 if (d) {
100 d_delete(dentry); /* make sure ->d_prune() does nothing */
101 dput(dentry);
102 cpu_relax();
103 goto again;
104 }
105 goto got_it;
106}
107
108int ns_get_name(char *buf, size_t size, struct task_struct *task,
109 const struct proc_ns_operations *ns_ops)
110{
111 struct ns_common *ns;
112 int res = -ENOENT;
113 ns = ns_ops->get(task);
114 if (ns) {
115 res = snprintf(buf, size, "%s:[%u]", ns_ops->name, ns->inum);
116 ns_ops->put(ns);
117 }
118 return res;
119}
120
121struct file *proc_ns_fget(int fd)
122{
123 struct file *file;
124
125 file = fget(fd);
126 if (!file)
127 return ERR_PTR(-EBADF);
128
129 if (file->f_op != &ns_file_operations)
130 goto out_invalid;
131
132 return file;
133
134out_invalid:
135 fput(file);
136 return ERR_PTR(-EINVAL);
137}
138
139static const struct super_operations nsfs_ops = {
140 .statfs = simple_statfs,
141 .evict_inode = nsfs_evict,
142};
143static struct dentry *nsfs_mount(struct file_system_type *fs_type,
144 int flags, const char *dev_name, void *data)
145{
146 return mount_pseudo(fs_type, "nsfs:", &nsfs_ops,
147 &ns_dentry_operations, NSFS_MAGIC);
148}
149static struct file_system_type nsfs = {
150 .name = "nsfs",
151 .mount = nsfs_mount,
152 .kill_sb = kill_anon_super,
153};
154
155void __init nsfs_init(void)
156{
157 nsfs_mnt = kern_mount(&nsfs);
158 if (IS_ERR(nsfs_mnt))
159 panic("can't set nsfs up\n");
160 nsfs_mnt->mnt_sb->s_flags &= ~MS_NOUSER;
161}
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 333080d7a671..8420a2f80811 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -32,8 +32,6 @@ static void proc_evict_inode(struct inode *inode)
32{ 32{
33 struct proc_dir_entry *de; 33 struct proc_dir_entry *de;
34 struct ctl_table_header *head; 34 struct ctl_table_header *head;
35 const struct proc_ns_operations *ns_ops;
36 void *ns;
37 35
38 truncate_inode_pages_final(&inode->i_data); 36 truncate_inode_pages_final(&inode->i_data);
39 clear_inode(inode); 37 clear_inode(inode);
@@ -50,11 +48,6 @@ static void proc_evict_inode(struct inode *inode)
50 RCU_INIT_POINTER(PROC_I(inode)->sysctl, NULL); 48 RCU_INIT_POINTER(PROC_I(inode)->sysctl, NULL);
51 sysctl_head_put(head); 49 sysctl_head_put(head);
52 } 50 }
53 /* Release any associated namespace */
54 ns_ops = PROC_I(inode)->ns.ns_ops;
55 ns = PROC_I(inode)->ns.ns;
56 if (ns_ops && ns)
57 ns_ops->put(ns);
58} 51}
59 52
60static struct kmem_cache * proc_inode_cachep; 53static struct kmem_cache * proc_inode_cachep;
@@ -73,8 +66,7 @@ static struct inode *proc_alloc_inode(struct super_block *sb)
73 ei->pde = NULL; 66 ei->pde = NULL;
74 ei->sysctl = NULL; 67 ei->sysctl = NULL;
75 ei->sysctl_entry = NULL; 68 ei->sysctl_entry = NULL;
76 ei->ns.ns = NULL; 69 ei->ns_ops = NULL;
77 ei->ns.ns_ops = NULL;
78 inode = &ei->vfs_inode; 70 inode = &ei->vfs_inode;
79 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; 71 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
80 return inode; 72 return inode;
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 7fb1a4869fd0..6fcdba573e0f 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -65,7 +65,7 @@ struct proc_inode {
65 struct proc_dir_entry *pde; 65 struct proc_dir_entry *pde;
66 struct ctl_table_header *sysctl; 66 struct ctl_table_header *sysctl;
67 struct ctl_table *sysctl_entry; 67 struct ctl_table *sysctl_entry;
68 struct proc_ns ns; 68 const struct proc_ns_operations *ns_ops;
69 struct inode vfs_inode; 69 struct inode vfs_inode;
70}; 70};
71 71
diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
index 89026095f2b5..c9eac4563fa8 100644
--- a/fs/proc/namespaces.c
+++ b/fs/proc/namespaces.c
@@ -1,10 +1,6 @@
1#include <linux/proc_fs.h> 1#include <linux/proc_fs.h>
2#include <linux/nsproxy.h> 2#include <linux/nsproxy.h>
3#include <linux/sched.h>
4#include <linux/ptrace.h> 3#include <linux/ptrace.h>
5#include <linux/fs_struct.h>
6#include <linux/mount.h>
7#include <linux/path.h>
8#include <linux/namei.h> 4#include <linux/namei.h>
9#include <linux/file.h> 5#include <linux/file.h>
10#include <linux/utsname.h> 6#include <linux/utsname.h>
@@ -34,138 +30,45 @@ static const struct proc_ns_operations *ns_entries[] = {
34 &mntns_operations, 30 &mntns_operations,
35}; 31};
36 32
37static const struct file_operations ns_file_operations = {
38 .llseek = no_llseek,
39};
40
41static const struct inode_operations ns_inode_operations = {
42 .setattr = proc_setattr,
43};
44
45static char *ns_dname(struct dentry *dentry, char *buffer, int buflen)
46{
47 struct inode *inode = dentry->d_inode;
48 const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns.ns_ops;
49
50 return dynamic_dname(dentry, buffer, buflen, "%s:[%lu]",
51 ns_ops->name, inode->i_ino);
52}
53
54const struct dentry_operations ns_dentry_operations =
55{
56 .d_delete = always_delete_dentry,
57 .d_dname = ns_dname,
58};
59
60static struct dentry *proc_ns_get_dentry(struct super_block *sb,
61 struct task_struct *task, const struct proc_ns_operations *ns_ops)
62{
63 struct dentry *dentry, *result;
64 struct inode *inode;
65 struct proc_inode *ei;
66 struct qstr qname = { .name = "", };
67 void *ns;
68
69 ns = ns_ops->get(task);
70 if (!ns)
71 return ERR_PTR(-ENOENT);
72
73 dentry = d_alloc_pseudo(sb, &qname);
74 if (!dentry) {
75 ns_ops->put(ns);
76 return ERR_PTR(-ENOMEM);
77 }
78
79 inode = iget_locked(sb, ns_ops->inum(ns));
80 if (!inode) {
81 dput(dentry);
82 ns_ops->put(ns);
83 return ERR_PTR(-ENOMEM);
84 }
85
86 ei = PROC_I(inode);
87 if (inode->i_state & I_NEW) {
88 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
89 inode->i_op = &ns_inode_operations;
90 inode->i_mode = S_IFREG | S_IRUGO;
91 inode->i_fop = &ns_file_operations;
92 ei->ns.ns_ops = ns_ops;
93 ei->ns.ns = ns;
94 unlock_new_inode(inode);
95 } else {
96 ns_ops->put(ns);
97 }
98
99 d_set_d_op(dentry, &ns_dentry_operations);
100 result = d_instantiate_unique(dentry, inode);
101 if (result) {
102 dput(dentry);
103 dentry = result;
104 }
105
106 return dentry;
107}
108
109static void *proc_ns_follow_link(struct dentry *dentry, struct nameidata *nd) 33static void *proc_ns_follow_link(struct dentry *dentry, struct nameidata *nd)
110{ 34{
111 struct inode *inode = dentry->d_inode; 35 struct inode *inode = dentry->d_inode;
112 struct super_block *sb = inode->i_sb; 36 const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops;
113 struct proc_inode *ei = PROC_I(inode);
114 struct task_struct *task; 37 struct task_struct *task;
115 struct path ns_path; 38 struct path ns_path;
116 void *error = ERR_PTR(-EACCES); 39 void *error = ERR_PTR(-EACCES);
117 40
118 task = get_proc_task(inode); 41 task = get_proc_task(inode);
119 if (!task) 42 if (!task)
120 goto out; 43 return error;
121 44
122 if (!ptrace_may_access(task, PTRACE_MODE_READ)) 45 if (ptrace_may_access(task, PTRACE_MODE_READ)) {
123 goto out_put_task; 46 error = ns_get_path(&ns_path, task, ns_ops);
124 47 if (!error)
125 ns_path.dentry = proc_ns_get_dentry(sb, task, ei->ns.ns_ops); 48 nd_jump_link(nd, &ns_path);
126 if (IS_ERR(ns_path.dentry)) {
127 error = ERR_CAST(ns_path.dentry);
128 goto out_put_task;
129 } 49 }
130
131 ns_path.mnt = mntget(nd->path.mnt);
132 nd_jump_link(nd, &ns_path);
133 error = NULL;
134
135out_put_task:
136 put_task_struct(task); 50 put_task_struct(task);
137out:
138 return error; 51 return error;
139} 52}
140 53
141static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int buflen) 54static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int buflen)
142{ 55{
143 struct inode *inode = dentry->d_inode; 56 struct inode *inode = dentry->d_inode;
144 struct proc_inode *ei = PROC_I(inode); 57 const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops;
145 const struct proc_ns_operations *ns_ops = ei->ns.ns_ops;
146 struct task_struct *task; 58 struct task_struct *task;
147 void *ns;
148 char name[50]; 59 char name[50];
149 int res = -EACCES; 60 int res = -EACCES;
150 61
151 task = get_proc_task(inode); 62 task = get_proc_task(inode);
152 if (!task) 63 if (!task)
153 goto out; 64 return res;
154
155 if (!ptrace_may_access(task, PTRACE_MODE_READ))
156 goto out_put_task;
157 65
158 res = -ENOENT; 66 if (ptrace_may_access(task, PTRACE_MODE_READ)) {
159 ns = ns_ops->get(task); 67 res = ns_get_name(name, sizeof(name), task, ns_ops);
160 if (!ns) 68 if (res >= 0)
161 goto out_put_task; 69 res = readlink_copy(buffer, buflen, name);
162 70 }
163 snprintf(name, sizeof(name), "%s:[%u]", ns_ops->name, ns_ops->inum(ns));
164 res = readlink_copy(buffer, buflen, name);
165 ns_ops->put(ns);
166out_put_task:
167 put_task_struct(task); 71 put_task_struct(task);
168out:
169 return res; 72 return res;
170} 73}
171 74
@@ -189,7 +92,7 @@ static int proc_ns_instantiate(struct inode *dir,
189 ei = PROC_I(inode); 92 ei = PROC_I(inode);
190 inode->i_mode = S_IFLNK|S_IRWXUGO; 93 inode->i_mode = S_IFLNK|S_IRWXUGO;
191 inode->i_op = &proc_ns_link_inode_operations; 94 inode->i_op = &proc_ns_link_inode_operations;
192 ei->ns.ns_ops = ns_ops; 95 ei->ns_ops = ns_ops;
193 96
194 d_set_d_op(dentry, &pid_dentry_operations); 97 d_set_d_op(dentry, &pid_dentry_operations);
195 d_add(dentry, inode); 98 d_add(dentry, inode);
@@ -267,31 +170,3 @@ const struct inode_operations proc_ns_dir_inode_operations = {
267 .getattr = pid_getattr, 170 .getattr = pid_getattr,
268 .setattr = proc_setattr, 171 .setattr = proc_setattr,
269}; 172};
270
271struct file *proc_ns_fget(int fd)
272{
273 struct file *file;
274
275 file = fget(fd);
276 if (!file)
277 return ERR_PTR(-EBADF);
278
279 if (file->f_op != &ns_file_operations)
280 goto out_invalid;
281
282 return file;
283
284out_invalid:
285 fput(file);
286 return ERR_PTR(-EINVAL);
287}
288
289struct proc_ns *get_proc_ns(struct inode *inode)
290{
291 return &PROC_I(inode)->ns;
292}
293
294bool proc_ns_inode(struct inode *inode)
295{
296 return inode->i_fop == &ns_file_operations;
297}