aboutsummaryrefslogtreecommitdiffstats
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
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
-rw-r--r--arch/ia64/kernel/perfmon.c10
-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
-rw-r--r--include/linux/fs.h1
-rw-r--r--include/linux/ipc_namespace.h3
-rw-r--r--include/linux/namei.h25
-rw-r--r--include/linux/ns_common.h12
-rw-r--r--include/linux/pid_namespace.h3
-rw-r--r--include/linux/proc_ns.h43
-rw-r--r--include/linux/user_namespace.h3
-rw-r--r--include/linux/utsname.h3
-rw-r--r--include/net/net_namespace.h3
-rw-r--r--include/uapi/linux/magic.h1
-rw-r--r--init/main.c2
-rw-r--r--init/version.c5
-rw-r--r--ipc/msgutil.c5
-rw-r--r--ipc/namespace.c32
-rw-r--r--kernel/nsproxy.c10
-rw-r--r--kernel/pid.c5
-rw-r--r--kernel/pid_namespace.c29
-rw-r--r--kernel/user.c5
-rw-r--r--kernel/user_namespace.c29
-rw-r--r--kernel/utsname.c31
-rw-r--r--net/Makefile2
-rw-r--r--net/core/net_namespace.c39
-rw-r--r--net/nonet.c26
-rw-r--r--net/socket.c19
36 files changed, 416 insertions, 430 deletions
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index dc063fe6646a..5f4243f0acfa 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -2145,22 +2145,12 @@ doit:
2145 return 0; 2145 return 0;
2146} 2146}
2147 2147
2148static int
2149pfm_no_open(struct inode *irrelevant, struct file *dontcare)
2150{
2151 DPRINT(("pfm_no_open called\n"));
2152 return -ENXIO;
2153}
2154
2155
2156
2157static const struct file_operations pfm_file_ops = { 2148static const struct file_operations pfm_file_ops = {
2158 .llseek = no_llseek, 2149 .llseek = no_llseek,
2159 .read = pfm_read, 2150 .read = pfm_read,
2160 .write = pfm_write, 2151 .write = pfm_write,
2161 .poll = pfm_poll, 2152 .poll = pfm_poll,
2162 .unlocked_ioctl = pfm_ioctl, 2153 .unlocked_ioctl = pfm_ioctl,
2163 .open = pfm_no_open, /* special open code to disallow open via /proc */
2164 .fasync = pfm_fasync, 2154 .fasync = pfm_fasync,
2165 .release = pfm_close, 2155 .release = pfm_close,
2166 .flush = pfm_flush 2156 .flush = pfm_flush
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}
diff --git a/include/linux/fs.h b/include/linux/fs.h
index eeaccd37184f..f90c0282c114 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2176,7 +2176,6 @@ static inline int sb_is_blkdev_sb(struct super_block *sb)
2176extern int sync_filesystem(struct super_block *); 2176extern int sync_filesystem(struct super_block *);
2177extern const struct file_operations def_blk_fops; 2177extern const struct file_operations def_blk_fops;
2178extern const struct file_operations def_chr_fops; 2178extern const struct file_operations def_chr_fops;
2179extern const struct file_operations bad_sock_fops;
2180#ifdef CONFIG_BLOCK 2179#ifdef CONFIG_BLOCK
2181extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long); 2180extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long);
2182extern int blkdev_ioctl(struct block_device *, fmode_t, unsigned, unsigned long); 2181extern int blkdev_ioctl(struct block_device *, fmode_t, unsigned, unsigned long);
diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h
index e365d5ec69cb..1eee6bcfcf76 100644
--- a/include/linux/ipc_namespace.h
+++ b/include/linux/ipc_namespace.h
@@ -6,6 +6,7 @@
6#include <linux/rwsem.h> 6#include <linux/rwsem.h>
7#include <linux/notifier.h> 7#include <linux/notifier.h>
8#include <linux/nsproxy.h> 8#include <linux/nsproxy.h>
9#include <linux/ns_common.h>
9 10
10struct user_namespace; 11struct user_namespace;
11 12
@@ -58,7 +59,7 @@ struct ipc_namespace {
58 /* user_ns which owns the ipc ns */ 59 /* user_ns which owns the ipc ns */
59 struct user_namespace *user_ns; 60 struct user_namespace *user_ns;
60 61
61 unsigned int proc_inum; 62 struct ns_common ns;
62}; 63};
63 64
64extern struct ipc_namespace init_ipc_ns; 65extern struct ipc_namespace init_ipc_ns;
diff --git a/include/linux/namei.h b/include/linux/namei.h
index 492de72560fa..c8990779f0c3 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -7,21 +7,10 @@
7#include <linux/path.h> 7#include <linux/path.h>
8 8
9struct vfsmount; 9struct vfsmount;
10struct nameidata;
10 11
11enum { MAX_NESTED_LINKS = 8 }; 12enum { MAX_NESTED_LINKS = 8 };
12 13
13struct nameidata {
14 struct path path;
15 struct qstr last;
16 struct path root;
17 struct inode *inode; /* path.dentry.d_inode */
18 unsigned int flags;
19 unsigned seq, m_seq;
20 int last_type;
21 unsigned depth;
22 char *saved_names[MAX_NESTED_LINKS + 1];
23};
24
25/* 14/*
26 * Type of the last component on LOOKUP_PARENT 15 * Type of the last component on LOOKUP_PARENT
27 */ 16 */
@@ -82,16 +71,8 @@ extern struct dentry *lock_rename(struct dentry *, struct dentry *);
82extern void unlock_rename(struct dentry *, struct dentry *); 71extern void unlock_rename(struct dentry *, struct dentry *);
83 72
84extern void nd_jump_link(struct nameidata *nd, struct path *path); 73extern void nd_jump_link(struct nameidata *nd, struct path *path);
85 74extern void nd_set_link(struct nameidata *nd, char *path);
86static inline void nd_set_link(struct nameidata *nd, char *path) 75extern char *nd_get_link(struct nameidata *nd);
87{
88 nd->saved_names[nd->depth] = path;
89}
90
91static inline char *nd_get_link(struct nameidata *nd)
92{
93 return nd->saved_names[nd->depth];
94}
95 76
96static inline void nd_terminate_link(void *name, size_t len, size_t maxlen) 77static inline void nd_terminate_link(void *name, size_t len, size_t maxlen)
97{ 78{
diff --git a/include/linux/ns_common.h b/include/linux/ns_common.h
new file mode 100644
index 000000000000..85a5c8c16be9
--- /dev/null
+++ b/include/linux/ns_common.h
@@ -0,0 +1,12 @@
1#ifndef _LINUX_NS_COMMON_H
2#define _LINUX_NS_COMMON_H
3
4struct proc_ns_operations;
5
6struct ns_common {
7 atomic_long_t stashed;
8 const struct proc_ns_operations *ops;
9 unsigned int inum;
10};
11
12#endif
diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h
index 1997ffc295a7..b9cf6c51b181 100644
--- a/include/linux/pid_namespace.h
+++ b/include/linux/pid_namespace.h
@@ -8,6 +8,7 @@
8#include <linux/threads.h> 8#include <linux/threads.h>
9#include <linux/nsproxy.h> 9#include <linux/nsproxy.h>
10#include <linux/kref.h> 10#include <linux/kref.h>
11#include <linux/ns_common.h>
11 12
12struct pidmap { 13struct pidmap {
13 atomic_t nr_free; 14 atomic_t nr_free;
@@ -43,7 +44,7 @@ struct pid_namespace {
43 kgid_t pid_gid; 44 kgid_t pid_gid;
44 int hide_pid; 45 int hide_pid;
45 int reboot; /* group exit code if this pidns was rebooted */ 46 int reboot; /* group exit code if this pidns was rebooted */
46 unsigned int proc_inum; 47 struct ns_common ns;
47}; 48};
48 49
49extern struct pid_namespace init_pid_ns; 50extern struct pid_namespace init_pid_ns;
diff --git a/include/linux/proc_ns.h b/include/linux/proc_ns.h
index 34a1e105bef4..42dfc615dbf8 100644
--- a/include/linux/proc_ns.h
+++ b/include/linux/proc_ns.h
@@ -4,21 +4,18 @@
4#ifndef _LINUX_PROC_NS_H 4#ifndef _LINUX_PROC_NS_H
5#define _LINUX_PROC_NS_H 5#define _LINUX_PROC_NS_H
6 6
7#include <linux/ns_common.h>
8
7struct pid_namespace; 9struct pid_namespace;
8struct nsproxy; 10struct nsproxy;
11struct path;
9 12
10struct proc_ns_operations { 13struct proc_ns_operations {
11 const char *name; 14 const char *name;
12 int type; 15 int type;
13 void *(*get)(struct task_struct *task); 16 struct ns_common *(*get)(struct task_struct *task);
14 void (*put)(void *ns); 17 void (*put)(struct ns_common *ns);
15 int (*install)(struct nsproxy *nsproxy, void *ns); 18 int (*install)(struct nsproxy *nsproxy, struct ns_common *ns);
16 unsigned int (*inum)(void *ns);
17};
18
19struct proc_ns {
20 void *ns;
21 const struct proc_ns_operations *ns_ops;
22}; 19};
23 20
24extern const struct proc_ns_operations netns_operations; 21extern const struct proc_ns_operations netns_operations;
@@ -43,32 +40,38 @@ enum {
43 40
44extern int pid_ns_prepare_proc(struct pid_namespace *ns); 41extern int pid_ns_prepare_proc(struct pid_namespace *ns);
45extern void pid_ns_release_proc(struct pid_namespace *ns); 42extern void pid_ns_release_proc(struct pid_namespace *ns);
46extern struct file *proc_ns_fget(int fd);
47extern struct proc_ns *get_proc_ns(struct inode *);
48extern int proc_alloc_inum(unsigned int *pino); 43extern int proc_alloc_inum(unsigned int *pino);
49extern void proc_free_inum(unsigned int inum); 44extern void proc_free_inum(unsigned int inum);
50extern bool proc_ns_inode(struct inode *inode);
51 45
52#else /* CONFIG_PROC_FS */ 46#else /* CONFIG_PROC_FS */
53 47
54static inline int pid_ns_prepare_proc(struct pid_namespace *ns) { return 0; } 48static inline int pid_ns_prepare_proc(struct pid_namespace *ns) { return 0; }
55static inline void pid_ns_release_proc(struct pid_namespace *ns) {} 49static inline void pid_ns_release_proc(struct pid_namespace *ns) {}
56 50
57static inline struct file *proc_ns_fget(int fd)
58{
59 return ERR_PTR(-EINVAL);
60}
61
62static inline struct proc_ns *get_proc_ns(struct inode *inode) { return NULL; }
63
64static inline int proc_alloc_inum(unsigned int *inum) 51static inline int proc_alloc_inum(unsigned int *inum)
65{ 52{
66 *inum = 1; 53 *inum = 1;
67 return 0; 54 return 0;
68} 55}
69static inline void proc_free_inum(unsigned int inum) {} 56static inline void proc_free_inum(unsigned int inum) {}
70static inline bool proc_ns_inode(struct inode *inode) { return false; }
71 57
72#endif /* CONFIG_PROC_FS */ 58#endif /* CONFIG_PROC_FS */
73 59
60static inline int ns_alloc_inum(struct ns_common *ns)
61{
62 atomic_long_set(&ns->stashed, 0);
63 return proc_alloc_inum(&ns->inum);
64}
65
66#define ns_free_inum(ns) proc_free_inum((ns)->inum)
67
68extern struct file *proc_ns_fget(int fd);
69#define get_proc_ns(inode) ((struct ns_common *)(inode)->i_private)
70extern void *ns_get_path(struct path *path, struct task_struct *task,
71 const struct proc_ns_operations *ns_ops);
72
73extern int ns_get_name(char *buf, size_t size, struct task_struct *task,
74 const struct proc_ns_operations *ns_ops);
75extern void nsfs_init(void);
76
74#endif /* _LINUX_PROC_NS_H */ 77#endif /* _LINUX_PROC_NS_H */
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index e95372654f09..4cf06c140e21 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -3,6 +3,7 @@
3 3
4#include <linux/kref.h> 4#include <linux/kref.h>
5#include <linux/nsproxy.h> 5#include <linux/nsproxy.h>
6#include <linux/ns_common.h>
6#include <linux/sched.h> 7#include <linux/sched.h>
7#include <linux/err.h> 8#include <linux/err.h>
8 9
@@ -26,7 +27,7 @@ struct user_namespace {
26 int level; 27 int level;
27 kuid_t owner; 28 kuid_t owner;
28 kgid_t group; 29 kgid_t group;
29 unsigned int proc_inum; 30 struct ns_common ns;
30 31
31 /* Register of per-UID persistent keyrings for this namespace */ 32 /* Register of per-UID persistent keyrings for this namespace */
32#ifdef CONFIG_PERSISTENT_KEYRINGS 33#ifdef CONFIG_PERSISTENT_KEYRINGS
diff --git a/include/linux/utsname.h b/include/linux/utsname.h
index 239e27733d6c..5093f58ae192 100644
--- a/include/linux/utsname.h
+++ b/include/linux/utsname.h
@@ -5,6 +5,7 @@
5#include <linux/sched.h> 5#include <linux/sched.h>
6#include <linux/kref.h> 6#include <linux/kref.h>
7#include <linux/nsproxy.h> 7#include <linux/nsproxy.h>
8#include <linux/ns_common.h>
8#include <linux/err.h> 9#include <linux/err.h>
9#include <uapi/linux/utsname.h> 10#include <uapi/linux/utsname.h>
10 11
@@ -23,7 +24,7 @@ struct uts_namespace {
23 struct kref kref; 24 struct kref kref;
24 struct new_utsname name; 25 struct new_utsname name;
25 struct user_namespace *user_ns; 26 struct user_namespace *user_ns;
26 unsigned int proc_inum; 27 struct ns_common ns;
27}; 28};
28extern struct uts_namespace init_uts_ns; 29extern struct uts_namespace init_uts_ns;
29 30
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index e0d64667a4b3..2e8756b8c775 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -26,6 +26,7 @@
26#endif 26#endif
27#include <net/netns/nftables.h> 27#include <net/netns/nftables.h>
28#include <net/netns/xfrm.h> 28#include <net/netns/xfrm.h>
29#include <linux/ns_common.h>
29 30
30struct user_namespace; 31struct user_namespace;
31struct proc_dir_entry; 32struct proc_dir_entry;
@@ -60,7 +61,7 @@ struct net {
60 61
61 struct user_namespace *user_ns; /* Owning user namespace */ 62 struct user_namespace *user_ns; /* Owning user namespace */
62 63
63 unsigned int proc_inum; 64 struct ns_common ns;
64 65
65 struct proc_dir_entry *proc_net; 66 struct proc_dir_entry *proc_net;
66 struct proc_dir_entry *proc_net_stat; 67 struct proc_dir_entry *proc_net_stat;
diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h
index 77c60311a6c6..7d664ea85ebd 100644
--- a/include/uapi/linux/magic.h
+++ b/include/uapi/linux/magic.h
@@ -72,5 +72,6 @@
72#define MTD_INODE_FS_MAGIC 0x11307854 72#define MTD_INODE_FS_MAGIC 0x11307854
73#define ANON_INODE_FS_MAGIC 0x09041934 73#define ANON_INODE_FS_MAGIC 0x09041934
74#define BTRFS_TEST_MAGIC 0x73727279 74#define BTRFS_TEST_MAGIC 0x73727279
75#define NSFS_MAGIC 0x6e736673
75 76
76#endif /* __LINUX_MAGIC_H__ */ 77#endif /* __LINUX_MAGIC_H__ */
diff --git a/init/main.c b/init/main.c
index 747ecc4c0a19..61b993767db5 100644
--- a/init/main.c
+++ b/init/main.c
@@ -79,6 +79,7 @@
79#include <linux/random.h> 79#include <linux/random.h>
80#include <linux/list.h> 80#include <linux/list.h>
81#include <linux/integrity.h> 81#include <linux/integrity.h>
82#include <linux/proc_ns.h>
82 83
83#include <asm/io.h> 84#include <asm/io.h>
84#include <asm/bugs.h> 85#include <asm/bugs.h>
@@ -665,6 +666,7 @@ asmlinkage __visible void __init start_kernel(void)
665 /* rootfs populating might need page-writeback */ 666 /* rootfs populating might need page-writeback */
666 page_writeback_init(); 667 page_writeback_init();
667 proc_root_init(); 668 proc_root_init();
669 nsfs_init();
668 cgroup_init(); 670 cgroup_init();
669 cpuset_init(); 671 cpuset_init();
670 taskstats_init_early(); 672 taskstats_init_early();
diff --git a/init/version.c b/init/version.c
index 1a4718e500fe..fe41a63efed6 100644
--- a/init/version.c
+++ b/init/version.c
@@ -35,7 +35,10 @@ struct uts_namespace init_uts_ns = {
35 .domainname = UTS_DOMAINNAME, 35 .domainname = UTS_DOMAINNAME,
36 }, 36 },
37 .user_ns = &init_user_ns, 37 .user_ns = &init_user_ns,
38 .proc_inum = PROC_UTS_INIT_INO, 38 .ns.inum = PROC_UTS_INIT_INO,
39#ifdef CONFIG_UTS_NS
40 .ns.ops = &utsns_operations,
41#endif
39}; 42};
40EXPORT_SYMBOL_GPL(init_uts_ns); 43EXPORT_SYMBOL_GPL(init_uts_ns);
41 44
diff --git a/ipc/msgutil.c b/ipc/msgutil.c
index 7e7095974d54..2b491590ebab 100644
--- a/ipc/msgutil.c
+++ b/ipc/msgutil.c
@@ -31,7 +31,10 @@ DEFINE_SPINLOCK(mq_lock);
31struct ipc_namespace init_ipc_ns = { 31struct ipc_namespace init_ipc_ns = {
32 .count = ATOMIC_INIT(1), 32 .count = ATOMIC_INIT(1),
33 .user_ns = &init_user_ns, 33 .user_ns = &init_user_ns,
34 .proc_inum = PROC_IPC_INIT_INO, 34 .ns.inum = PROC_IPC_INIT_INO,
35#ifdef CONFIG_IPC_NS
36 .ns.ops = &ipcns_operations,
37#endif
35}; 38};
36 39
37atomic_t nr_ipc_ns = ATOMIC_INIT(1); 40atomic_t nr_ipc_ns = ATOMIC_INIT(1);
diff --git a/ipc/namespace.c b/ipc/namespace.c
index 1a3ffd40356e..068caf18d565 100644
--- a/ipc/namespace.c
+++ b/ipc/namespace.c
@@ -26,16 +26,17 @@ static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns,
26 if (ns == NULL) 26 if (ns == NULL)
27 return ERR_PTR(-ENOMEM); 27 return ERR_PTR(-ENOMEM);
28 28
29 err = proc_alloc_inum(&ns->proc_inum); 29 err = ns_alloc_inum(&ns->ns);
30 if (err) { 30 if (err) {
31 kfree(ns); 31 kfree(ns);
32 return ERR_PTR(err); 32 return ERR_PTR(err);
33 } 33 }
34 ns->ns.ops = &ipcns_operations;
34 35
35 atomic_set(&ns->count, 1); 36 atomic_set(&ns->count, 1);
36 err = mq_init_ns(ns); 37 err = mq_init_ns(ns);
37 if (err) { 38 if (err) {
38 proc_free_inum(ns->proc_inum); 39 ns_free_inum(&ns->ns);
39 kfree(ns); 40 kfree(ns);
40 return ERR_PTR(err); 41 return ERR_PTR(err);
41 } 42 }
@@ -97,7 +98,7 @@ static void free_ipc_ns(struct ipc_namespace *ns)
97 atomic_dec(&nr_ipc_ns); 98 atomic_dec(&nr_ipc_ns);
98 99
99 put_user_ns(ns->user_ns); 100 put_user_ns(ns->user_ns);
100 proc_free_inum(ns->proc_inum); 101 ns_free_inum(&ns->ns);
101 kfree(ns); 102 kfree(ns);
102} 103}
103 104
@@ -127,7 +128,12 @@ void put_ipc_ns(struct ipc_namespace *ns)
127 } 128 }
128} 129}
129 130
130static void *ipcns_get(struct task_struct *task) 131static inline struct ipc_namespace *to_ipc_ns(struct ns_common *ns)
132{
133 return container_of(ns, struct ipc_namespace, ns);
134}
135
136static struct ns_common *ipcns_get(struct task_struct *task)
131{ 137{
132 struct ipc_namespace *ns = NULL; 138 struct ipc_namespace *ns = NULL;
133 struct nsproxy *nsproxy; 139 struct nsproxy *nsproxy;
@@ -138,17 +144,17 @@ static void *ipcns_get(struct task_struct *task)
138 ns = get_ipc_ns(nsproxy->ipc_ns); 144 ns = get_ipc_ns(nsproxy->ipc_ns);
139 task_unlock(task); 145 task_unlock(task);
140 146
141 return ns; 147 return ns ? &ns->ns : NULL;
142} 148}
143 149
144static void ipcns_put(void *ns) 150static void ipcns_put(struct ns_common *ns)
145{ 151{
146 return put_ipc_ns(ns); 152 return put_ipc_ns(to_ipc_ns(ns));
147} 153}
148 154
149static int ipcns_install(struct nsproxy *nsproxy, void *new) 155static int ipcns_install(struct nsproxy *nsproxy, struct ns_common *new)
150{ 156{
151 struct ipc_namespace *ns = new; 157 struct ipc_namespace *ns = to_ipc_ns(new);
152 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) || 158 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) ||
153 !ns_capable(current_user_ns(), CAP_SYS_ADMIN)) 159 !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
154 return -EPERM; 160 return -EPERM;
@@ -160,18 +166,10 @@ static int ipcns_install(struct nsproxy *nsproxy, void *new)
160 return 0; 166 return 0;
161} 167}
162 168
163static unsigned int ipcns_inum(void *vp)
164{
165 struct ipc_namespace *ns = vp;
166
167 return ns->proc_inum;
168}
169
170const struct proc_ns_operations ipcns_operations = { 169const struct proc_ns_operations ipcns_operations = {
171 .name = "ipc", 170 .name = "ipc",
172 .type = CLONE_NEWIPC, 171 .type = CLONE_NEWIPC,
173 .get = ipcns_get, 172 .get = ipcns_get,
174 .put = ipcns_put, 173 .put = ipcns_put,
175 .install = ipcns_install, 174 .install = ipcns_install,
176 .inum = ipcns_inum,
177}; 175};
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index ef42d0ab3115..49746c81ad8d 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -220,11 +220,10 @@ void exit_task_namespaces(struct task_struct *p)
220 220
221SYSCALL_DEFINE2(setns, int, fd, int, nstype) 221SYSCALL_DEFINE2(setns, int, fd, int, nstype)
222{ 222{
223 const struct proc_ns_operations *ops;
224 struct task_struct *tsk = current; 223 struct task_struct *tsk = current;
225 struct nsproxy *new_nsproxy; 224 struct nsproxy *new_nsproxy;
226 struct proc_ns *ei;
227 struct file *file; 225 struct file *file;
226 struct ns_common *ns;
228 int err; 227 int err;
229 228
230 file = proc_ns_fget(fd); 229 file = proc_ns_fget(fd);
@@ -232,9 +231,8 @@ SYSCALL_DEFINE2(setns, int, fd, int, nstype)
232 return PTR_ERR(file); 231 return PTR_ERR(file);
233 232
234 err = -EINVAL; 233 err = -EINVAL;
235 ei = get_proc_ns(file_inode(file)); 234 ns = get_proc_ns(file_inode(file));
236 ops = ei->ns_ops; 235 if (nstype && (ns->ops->type != nstype))
237 if (nstype && (ops->type != nstype))
238 goto out; 236 goto out;
239 237
240 new_nsproxy = create_new_namespaces(0, tsk, current_user_ns(), tsk->fs); 238 new_nsproxy = create_new_namespaces(0, tsk, current_user_ns(), tsk->fs);
@@ -243,7 +241,7 @@ SYSCALL_DEFINE2(setns, int, fd, int, nstype)
243 goto out; 241 goto out;
244 } 242 }
245 243
246 err = ops->install(new_nsproxy, ei->ns); 244 err = ns->ops->install(new_nsproxy, ns);
247 if (err) { 245 if (err) {
248 free_nsproxy(new_nsproxy); 246 free_nsproxy(new_nsproxy);
249 goto out; 247 goto out;
diff --git a/kernel/pid.c b/kernel/pid.c
index 82430c858d69..cd36a5e0d173 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -79,7 +79,10 @@ struct pid_namespace init_pid_ns = {
79 .level = 0, 79 .level = 0,
80 .child_reaper = &init_task, 80 .child_reaper = &init_task,
81 .user_ns = &init_user_ns, 81 .user_ns = &init_user_ns,
82 .proc_inum = PROC_PID_INIT_INO, 82 .ns.inum = PROC_PID_INIT_INO,
83#ifdef CONFIG_PID_NS
84 .ns.ops = &pidns_operations,
85#endif
83}; 86};
84EXPORT_SYMBOL_GPL(init_pid_ns); 87EXPORT_SYMBOL_GPL(init_pid_ns);
85 88
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index bc6d6a89b6e6..a65ba137fd15 100644
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -105,9 +105,10 @@ static struct pid_namespace *create_pid_namespace(struct user_namespace *user_ns
105 if (ns->pid_cachep == NULL) 105 if (ns->pid_cachep == NULL)
106 goto out_free_map; 106 goto out_free_map;
107 107
108 err = proc_alloc_inum(&ns->proc_inum); 108 err = ns_alloc_inum(&ns->ns);
109 if (err) 109 if (err)
110 goto out_free_map; 110 goto out_free_map;
111 ns->ns.ops = &pidns_operations;
111 112
112 kref_init(&ns->kref); 113 kref_init(&ns->kref);
113 ns->level = level; 114 ns->level = level;
@@ -142,7 +143,7 @@ static void destroy_pid_namespace(struct pid_namespace *ns)
142{ 143{
143 int i; 144 int i;
144 145
145 proc_free_inum(ns->proc_inum); 146 ns_free_inum(&ns->ns);
146 for (i = 0; i < PIDMAP_ENTRIES; i++) 147 for (i = 0; i < PIDMAP_ENTRIES; i++)
147 kfree(ns->pidmap[i].page); 148 kfree(ns->pidmap[i].page);
148 put_user_ns(ns->user_ns); 149 put_user_ns(ns->user_ns);
@@ -333,7 +334,12 @@ int reboot_pid_ns(struct pid_namespace *pid_ns, int cmd)
333 return 0; 334 return 0;
334} 335}
335 336
336static void *pidns_get(struct task_struct *task) 337static inline struct pid_namespace *to_pid_ns(struct ns_common *ns)
338{
339 return container_of(ns, struct pid_namespace, ns);
340}
341
342static struct ns_common *pidns_get(struct task_struct *task)
337{ 343{
338 struct pid_namespace *ns; 344 struct pid_namespace *ns;
339 345
@@ -343,18 +349,18 @@ static void *pidns_get(struct task_struct *task)
343 get_pid_ns(ns); 349 get_pid_ns(ns);
344 rcu_read_unlock(); 350 rcu_read_unlock();
345 351
346 return ns; 352 return ns ? &ns->ns : NULL;
347} 353}
348 354
349static void pidns_put(void *ns) 355static void pidns_put(struct ns_common *ns)
350{ 356{
351 put_pid_ns(ns); 357 put_pid_ns(to_pid_ns(ns));
352} 358}
353 359
354static int pidns_install(struct nsproxy *nsproxy, void *ns) 360static int pidns_install(struct nsproxy *nsproxy, struct ns_common *ns)
355{ 361{
356 struct pid_namespace *active = task_active_pid_ns(current); 362 struct pid_namespace *active = task_active_pid_ns(current);
357 struct pid_namespace *ancestor, *new = ns; 363 struct pid_namespace *ancestor, *new = to_pid_ns(ns);
358 364
359 if (!ns_capable(new->user_ns, CAP_SYS_ADMIN) || 365 if (!ns_capable(new->user_ns, CAP_SYS_ADMIN) ||
360 !ns_capable(current_user_ns(), CAP_SYS_ADMIN)) 366 !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
@@ -382,19 +388,12 @@ static int pidns_install(struct nsproxy *nsproxy, void *ns)
382 return 0; 388 return 0;
383} 389}
384 390
385static unsigned int pidns_inum(void *ns)
386{
387 struct pid_namespace *pid_ns = ns;
388 return pid_ns->proc_inum;
389}
390
391const struct proc_ns_operations pidns_operations = { 391const struct proc_ns_operations pidns_operations = {
392 .name = "pid", 392 .name = "pid",
393 .type = CLONE_NEWPID, 393 .type = CLONE_NEWPID,
394 .get = pidns_get, 394 .get = pidns_get,
395 .put = pidns_put, 395 .put = pidns_put,
396 .install = pidns_install, 396 .install = pidns_install,
397 .inum = pidns_inum,
398}; 397};
399 398
400static __init int pid_namespaces_init(void) 399static __init int pid_namespaces_init(void)
diff --git a/kernel/user.c b/kernel/user.c
index 4efa39350e44..69b800aebf13 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -50,7 +50,10 @@ struct user_namespace init_user_ns = {
50 .count = ATOMIC_INIT(3), 50 .count = ATOMIC_INIT(3),
51 .owner = GLOBAL_ROOT_UID, 51 .owner = GLOBAL_ROOT_UID,
52 .group = GLOBAL_ROOT_GID, 52 .group = GLOBAL_ROOT_GID,
53 .proc_inum = PROC_USER_INIT_INO, 53 .ns.inum = PROC_USER_INIT_INO,
54#ifdef CONFIG_USER_NS
55 .ns.ops = &userns_operations,
56#endif
54#ifdef CONFIG_PERSISTENT_KEYRINGS 57#ifdef CONFIG_PERSISTENT_KEYRINGS
55 .persistent_keyring_register_sem = 58 .persistent_keyring_register_sem =
56 __RWSEM_INITIALIZER(init_user_ns.persistent_keyring_register_sem), 59 __RWSEM_INITIALIZER(init_user_ns.persistent_keyring_register_sem),
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index aa312b0dc3ec..1491ad00388f 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -86,11 +86,12 @@ int create_user_ns(struct cred *new)
86 if (!ns) 86 if (!ns)
87 return -ENOMEM; 87 return -ENOMEM;
88 88
89 ret = proc_alloc_inum(&ns->proc_inum); 89 ret = ns_alloc_inum(&ns->ns);
90 if (ret) { 90 if (ret) {
91 kmem_cache_free(user_ns_cachep, ns); 91 kmem_cache_free(user_ns_cachep, ns);
92 return ret; 92 return ret;
93 } 93 }
94 ns->ns.ops = &userns_operations;
94 95
95 atomic_set(&ns->count, 1); 96 atomic_set(&ns->count, 1);
96 /* Leave the new->user_ns reference with the new user namespace. */ 97 /* Leave the new->user_ns reference with the new user namespace. */
@@ -136,7 +137,7 @@ void free_user_ns(struct user_namespace *ns)
136#ifdef CONFIG_PERSISTENT_KEYRINGS 137#ifdef CONFIG_PERSISTENT_KEYRINGS
137 key_put(ns->persistent_keyring_register); 138 key_put(ns->persistent_keyring_register);
138#endif 139#endif
139 proc_free_inum(ns->proc_inum); 140 ns_free_inum(&ns->ns);
140 kmem_cache_free(user_ns_cachep, ns); 141 kmem_cache_free(user_ns_cachep, ns);
141 ns = parent; 142 ns = parent;
142 } while (atomic_dec_and_test(&parent->count)); 143 } while (atomic_dec_and_test(&parent->count));
@@ -841,7 +842,12 @@ static bool new_idmap_permitted(const struct file *file,
841 return false; 842 return false;
842} 843}
843 844
844static void *userns_get(struct task_struct *task) 845static inline struct user_namespace *to_user_ns(struct ns_common *ns)
846{
847 return container_of(ns, struct user_namespace, ns);
848}
849
850static struct ns_common *userns_get(struct task_struct *task)
845{ 851{
846 struct user_namespace *user_ns; 852 struct user_namespace *user_ns;
847 853
@@ -849,17 +855,17 @@ static void *userns_get(struct task_struct *task)
849 user_ns = get_user_ns(__task_cred(task)->user_ns); 855 user_ns = get_user_ns(__task_cred(task)->user_ns);
850 rcu_read_unlock(); 856 rcu_read_unlock();
851 857
852 return user_ns; 858 return user_ns ? &user_ns->ns : NULL;
853} 859}
854 860
855static void userns_put(void *ns) 861static void userns_put(struct ns_common *ns)
856{ 862{
857 put_user_ns(ns); 863 put_user_ns(to_user_ns(ns));
858} 864}
859 865
860static int userns_install(struct nsproxy *nsproxy, void *ns) 866static int userns_install(struct nsproxy *nsproxy, struct ns_common *ns)
861{ 867{
862 struct user_namespace *user_ns = ns; 868 struct user_namespace *user_ns = to_user_ns(ns);
863 struct cred *cred; 869 struct cred *cred;
864 870
865 /* Don't allow gaining capabilities by reentering 871 /* Don't allow gaining capabilities by reentering
@@ -888,19 +894,12 @@ static int userns_install(struct nsproxy *nsproxy, void *ns)
888 return commit_creds(cred); 894 return commit_creds(cred);
889} 895}
890 896
891static unsigned int userns_inum(void *ns)
892{
893 struct user_namespace *user_ns = ns;
894 return user_ns->proc_inum;
895}
896
897const struct proc_ns_operations userns_operations = { 897const struct proc_ns_operations userns_operations = {
898 .name = "user", 898 .name = "user",
899 .type = CLONE_NEWUSER, 899 .type = CLONE_NEWUSER,
900 .get = userns_get, 900 .get = userns_get,
901 .put = userns_put, 901 .put = userns_put,
902 .install = userns_install, 902 .install = userns_install,
903 .inum = userns_inum,
904}; 903};
905 904
906static __init int user_namespaces_init(void) 905static __init int user_namespaces_init(void)
diff --git a/kernel/utsname.c b/kernel/utsname.c
index 883aaaa7de8a..831ea7108232 100644
--- a/kernel/utsname.c
+++ b/kernel/utsname.c
@@ -42,12 +42,14 @@ static struct uts_namespace *clone_uts_ns(struct user_namespace *user_ns,
42 if (!ns) 42 if (!ns)
43 return ERR_PTR(-ENOMEM); 43 return ERR_PTR(-ENOMEM);
44 44
45 err = proc_alloc_inum(&ns->proc_inum); 45 err = ns_alloc_inum(&ns->ns);
46 if (err) { 46 if (err) {
47 kfree(ns); 47 kfree(ns);
48 return ERR_PTR(err); 48 return ERR_PTR(err);
49 } 49 }
50 50
51 ns->ns.ops = &utsns_operations;
52
51 down_read(&uts_sem); 53 down_read(&uts_sem);
52 memcpy(&ns->name, &old_ns->name, sizeof(ns->name)); 54 memcpy(&ns->name, &old_ns->name, sizeof(ns->name));
53 ns->user_ns = get_user_ns(user_ns); 55 ns->user_ns = get_user_ns(user_ns);
@@ -84,11 +86,16 @@ void free_uts_ns(struct kref *kref)
84 86
85 ns = container_of(kref, struct uts_namespace, kref); 87 ns = container_of(kref, struct uts_namespace, kref);
86 put_user_ns(ns->user_ns); 88 put_user_ns(ns->user_ns);
87 proc_free_inum(ns->proc_inum); 89 ns_free_inum(&ns->ns);
88 kfree(ns); 90 kfree(ns);
89} 91}
90 92
91static void *utsns_get(struct task_struct *task) 93static inline struct uts_namespace *to_uts_ns(struct ns_common *ns)
94{
95 return container_of(ns, struct uts_namespace, ns);
96}
97
98static struct ns_common *utsns_get(struct task_struct *task)
92{ 99{
93 struct uts_namespace *ns = NULL; 100 struct uts_namespace *ns = NULL;
94 struct nsproxy *nsproxy; 101 struct nsproxy *nsproxy;
@@ -101,17 +108,17 @@ static void *utsns_get(struct task_struct *task)
101 } 108 }
102 task_unlock(task); 109 task_unlock(task);
103 110
104 return ns; 111 return ns ? &ns->ns : NULL;
105} 112}
106 113
107static void utsns_put(void *ns) 114static void utsns_put(struct ns_common *ns)
108{ 115{
109 put_uts_ns(ns); 116 put_uts_ns(to_uts_ns(ns));
110} 117}
111 118
112static int utsns_install(struct nsproxy *nsproxy, void *new) 119static int utsns_install(struct nsproxy *nsproxy, struct ns_common *new)
113{ 120{
114 struct uts_namespace *ns = new; 121 struct uts_namespace *ns = to_uts_ns(new);
115 122
116 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) || 123 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) ||
117 !ns_capable(current_user_ns(), CAP_SYS_ADMIN)) 124 !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
@@ -123,18 +130,10 @@ static int utsns_install(struct nsproxy *nsproxy, void *new)
123 return 0; 130 return 0;
124} 131}
125 132
126static unsigned int utsns_inum(void *vp)
127{
128 struct uts_namespace *ns = vp;
129
130 return ns->proc_inum;
131}
132
133const struct proc_ns_operations utsns_operations = { 133const struct proc_ns_operations utsns_operations = {
134 .name = "uts", 134 .name = "uts",
135 .type = CLONE_NEWUTS, 135 .type = CLONE_NEWUTS,
136 .get = utsns_get, 136 .get = utsns_get,
137 .put = utsns_put, 137 .put = utsns_put,
138 .install = utsns_install, 138 .install = utsns_install,
139 .inum = utsns_inum,
140}; 139};
diff --git a/net/Makefile b/net/Makefile
index 95fc694e4ddc..38704bdf941a 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -5,8 +5,6 @@
5# Rewritten to use lists instead of if-statements. 5# Rewritten to use lists instead of if-statements.
6# 6#
7 7
8obj-y := nonet.o
9
10obj-$(CONFIG_NET) := socket.o core/ 8obj-$(CONFIG_NET) := socket.o core/
11 9
12tmp-$(CONFIG_COMPAT) := compat.o 10tmp-$(CONFIG_COMPAT) := compat.o
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 7f155175bba8..ce780c722e48 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -337,17 +337,17 @@ EXPORT_SYMBOL_GPL(__put_net);
337 337
338struct net *get_net_ns_by_fd(int fd) 338struct net *get_net_ns_by_fd(int fd)
339{ 339{
340 struct proc_ns *ei;
341 struct file *file; 340 struct file *file;
341 struct ns_common *ns;
342 struct net *net; 342 struct net *net;
343 343
344 file = proc_ns_fget(fd); 344 file = proc_ns_fget(fd);
345 if (IS_ERR(file)) 345 if (IS_ERR(file))
346 return ERR_CAST(file); 346 return ERR_CAST(file);
347 347
348 ei = get_proc_ns(file_inode(file)); 348 ns = get_proc_ns(file_inode(file));
349 if (ei->ns_ops == &netns_operations) 349 if (ns->ops == &netns_operations)
350 net = get_net(ei->ns); 350 net = get_net(container_of(ns, struct net, ns));
351 else 351 else
352 net = ERR_PTR(-EINVAL); 352 net = ERR_PTR(-EINVAL);
353 353
@@ -386,12 +386,15 @@ EXPORT_SYMBOL_GPL(get_net_ns_by_pid);
386 386
387static __net_init int net_ns_net_init(struct net *net) 387static __net_init int net_ns_net_init(struct net *net)
388{ 388{
389 return proc_alloc_inum(&net->proc_inum); 389#ifdef CONFIG_NET_NS
390 net->ns.ops = &netns_operations;
391#endif
392 return ns_alloc_inum(&net->ns);
390} 393}
391 394
392static __net_exit void net_ns_net_exit(struct net *net) 395static __net_exit void net_ns_net_exit(struct net *net)
393{ 396{
394 proc_free_inum(net->proc_inum); 397 ns_free_inum(&net->ns);
395} 398}
396 399
397static struct pernet_operations __net_initdata net_ns_ops = { 400static struct pernet_operations __net_initdata net_ns_ops = {
@@ -629,7 +632,7 @@ void unregister_pernet_device(struct pernet_operations *ops)
629EXPORT_SYMBOL_GPL(unregister_pernet_device); 632EXPORT_SYMBOL_GPL(unregister_pernet_device);
630 633
631#ifdef CONFIG_NET_NS 634#ifdef CONFIG_NET_NS
632static void *netns_get(struct task_struct *task) 635static struct ns_common *netns_get(struct task_struct *task)
633{ 636{
634 struct net *net = NULL; 637 struct net *net = NULL;
635 struct nsproxy *nsproxy; 638 struct nsproxy *nsproxy;
@@ -640,17 +643,22 @@ static void *netns_get(struct task_struct *task)
640 net = get_net(nsproxy->net_ns); 643 net = get_net(nsproxy->net_ns);
641 task_unlock(task); 644 task_unlock(task);
642 645
643 return net; 646 return net ? &net->ns : NULL;
644} 647}
645 648
646static void netns_put(void *ns) 649static inline struct net *to_net_ns(struct ns_common *ns)
647{ 650{
648 put_net(ns); 651 return container_of(ns, struct net, ns);
649} 652}
650 653
651static int netns_install(struct nsproxy *nsproxy, void *ns) 654static void netns_put(struct ns_common *ns)
652{ 655{
653 struct net *net = ns; 656 put_net(to_net_ns(ns));
657}
658
659static int netns_install(struct nsproxy *nsproxy, struct ns_common *ns)
660{
661 struct net *net = to_net_ns(ns);
654 662
655 if (!ns_capable(net->user_ns, CAP_SYS_ADMIN) || 663 if (!ns_capable(net->user_ns, CAP_SYS_ADMIN) ||
656 !ns_capable(current_user_ns(), CAP_SYS_ADMIN)) 664 !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
@@ -661,18 +669,11 @@ static int netns_install(struct nsproxy *nsproxy, void *ns)
661 return 0; 669 return 0;
662} 670}
663 671
664static unsigned int netns_inum(void *ns)
665{
666 struct net *net = ns;
667 return net->proc_inum;
668}
669
670const struct proc_ns_operations netns_operations = { 672const struct proc_ns_operations netns_operations = {
671 .name = "net", 673 .name = "net",
672 .type = CLONE_NEWNET, 674 .type = CLONE_NEWNET,
673 .get = netns_get, 675 .get = netns_get,
674 .put = netns_put, 676 .put = netns_put,
675 .install = netns_install, 677 .install = netns_install,
676 .inum = netns_inum,
677}; 678};
678#endif 679#endif
diff --git a/net/nonet.c b/net/nonet.c
deleted file mode 100644
index b1a73fda9c12..000000000000
--- a/net/nonet.c
+++ /dev/null
@@ -1,26 +0,0 @@
1/*
2 * net/nonet.c
3 *
4 * Dummy functions to allow us to configure network support entirely
5 * out of the kernel.
6 *
7 * Distributed under the terms of the GNU GPL version 2.
8 * Copyright (c) Matthew Wilcox 2003
9 */
10
11#include <linux/module.h>
12#include <linux/errno.h>
13#include <linux/fs.h>
14#include <linux/init.h>
15#include <linux/kernel.h>
16
17static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
18{
19 return -ENXIO;
20}
21
22const struct file_operations bad_sock_fops = {
23 .owner = THIS_MODULE,
24 .open = sock_no_open,
25 .llseek = noop_llseek,
26};
diff --git a/net/socket.c b/net/socket.c
index 8809afccf7fa..70bbde65e4ca 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -113,7 +113,6 @@ unsigned int sysctl_net_busy_read __read_mostly;
113unsigned int sysctl_net_busy_poll __read_mostly; 113unsigned int sysctl_net_busy_poll __read_mostly;
114#endif 114#endif
115 115
116static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
117static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov, 116static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov,
118 unsigned long nr_segs, loff_t pos); 117 unsigned long nr_segs, loff_t pos);
119static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov, 118static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
@@ -151,7 +150,6 @@ static const struct file_operations socket_file_ops = {
151 .compat_ioctl = compat_sock_ioctl, 150 .compat_ioctl = compat_sock_ioctl,
152#endif 151#endif
153 .mmap = sock_mmap, 152 .mmap = sock_mmap,
154 .open = sock_no_open, /* special open code to disallow open via /proc */
155 .release = sock_close, 153 .release = sock_close,
156 .fasync = sock_fasync, 154 .fasync = sock_fasync,
157 .sendpage = sock_sendpage, 155 .sendpage = sock_sendpage,
@@ -559,23 +557,6 @@ static struct socket *sock_alloc(void)
559 return sock; 557 return sock;
560} 558}
561 559
562/*
563 * In theory you can't get an open on this inode, but /proc provides
564 * a back door. Remember to keep it shut otherwise you'll let the
565 * creepy crawlies in.
566 */
567
568static int sock_no_open(struct inode *irrelevant, struct file *dontcare)
569{
570 return -ENXIO;
571}
572
573const struct file_operations bad_sock_fops = {
574 .owner = THIS_MODULE,
575 .open = sock_no_open,
576 .llseek = noop_llseek,
577};
578
579/** 560/**
580 * sock_release - close a socket 561 * sock_release - close a socket
581 * @sock: socket to close 562 * @sock: socket to close