aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2014-12-10 21:31:59 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2014-12-10 21:31:59 -0500
commit707c5960f102f8cdafb9406047b158abc71b391f (patch)
tree31d195b1c48cefa2d04da7cc801824f87a0a9887
parentba00410b8131b23edfb0e09f8b6dd26c8eb621fb (diff)
parent3d3d35b1e94ec918fc0ae670663235bf197d8609 (diff)
Merge branch 'nsfs' into for-next
-rw-r--r--fs/Makefile2
-rw-r--r--fs/internal.h5
-rw-r--r--fs/mount.h3
-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/ipc_namespace.h3
-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/core/net_namespace.c39
27 files changed, 353 insertions, 297 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/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/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 aa7a0ee182e1..d689fd6960d5 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -64,7 +64,7 @@ struct proc_inode {
64 struct proc_dir_entry *pde; 64 struct proc_dir_entry *pde;
65 struct ctl_table_header *sysctl; 65 struct ctl_table_header *sysctl;
66 struct ctl_table *sysctl_entry; 66 struct ctl_table *sysctl_entry;
67 struct proc_ns ns; 67 const struct proc_ns_operations *ns_ops;
68 struct inode vfs_inode; 68 struct inode vfs_inode;
69}; 69};
70 70
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/ipc_namespace.h b/include/linux/ipc_namespace.h
index 35e7eca4e33b..52a640128151 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
10/* 11/*
11 * ipc namespace events 12 * ipc namespace events
@@ -68,7 +69,7 @@ struct ipc_namespace {
68 /* user_ns which owns the ipc ns */ 69 /* user_ns which owns the ipc ns */
69 struct user_namespace *user_ns; 70 struct user_namespace *user_ns;
70 71
71 unsigned int proc_inum; 72 struct ns_common ns;
72}; 73};
73 74
74extern struct ipc_namespace init_ipc_ns; 75extern struct ipc_namespace init_ipc_ns;
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 321d0ceb26d3..40240c8e31e8 100644
--- a/init/main.c
+++ b/init/main.c
@@ -78,6 +78,7 @@
78#include <linux/context_tracking.h> 78#include <linux/context_tracking.h>
79#include <linux/random.h> 79#include <linux/random.h>
80#include <linux/list.h> 80#include <linux/list.h>
81#include <linux/proc_ns.h>
81 82
82#include <asm/io.h> 83#include <asm/io.h>
83#include <asm/bugs.h> 84#include <asm/bugs.h>
@@ -660,6 +661,7 @@ asmlinkage __visible void __init start_kernel(void)
660 /* rootfs populating might need page-writeback */ 661 /* rootfs populating might need page-writeback */
661 page_writeback_init(); 662 page_writeback_init();
662 proc_root_init(); 663 proc_root_init();
664 nsfs_init();
663 cgroup_init(); 665 cgroup_init();
664 cpuset_init(); 666 cpuset_init();
665 taskstats_init_early(); 667 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 b54468e48e32..382e2aa42d8a 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 }
@@ -119,7 +120,7 @@ static void free_ipc_ns(struct ipc_namespace *ns)
119 */ 120 */
120 ipcns_notify(IPCNS_REMOVED); 121 ipcns_notify(IPCNS_REMOVED);
121 put_user_ns(ns->user_ns); 122 put_user_ns(ns->user_ns);
122 proc_free_inum(ns->proc_inum); 123 ns_free_inum(&ns->ns);
123 kfree(ns); 124 kfree(ns);
124} 125}
125 126
@@ -149,7 +150,12 @@ void put_ipc_ns(struct ipc_namespace *ns)
149 } 150 }
150} 151}
151 152
152static void *ipcns_get(struct task_struct *task) 153static inline struct ipc_namespace *to_ipc_ns(struct ns_common *ns)
154{
155 return container_of(ns, struct ipc_namespace, ns);
156}
157
158static struct ns_common *ipcns_get(struct task_struct *task)
153{ 159{
154 struct ipc_namespace *ns = NULL; 160 struct ipc_namespace *ns = NULL;
155 struct nsproxy *nsproxy; 161 struct nsproxy *nsproxy;
@@ -160,17 +166,17 @@ static void *ipcns_get(struct task_struct *task)
160 ns = get_ipc_ns(nsproxy->ipc_ns); 166 ns = get_ipc_ns(nsproxy->ipc_ns);
161 task_unlock(task); 167 task_unlock(task);
162 168
163 return ns; 169 return ns ? &ns->ns : NULL;
164} 170}
165 171
166static void ipcns_put(void *ns) 172static void ipcns_put(struct ns_common *ns)
167{ 173{
168 return put_ipc_ns(ns); 174 return put_ipc_ns(to_ipc_ns(ns));
169} 175}
170 176
171static int ipcns_install(struct nsproxy *nsproxy, void *new) 177static int ipcns_install(struct nsproxy *nsproxy, struct ns_common *new)
172{ 178{
173 struct ipc_namespace *ns = new; 179 struct ipc_namespace *ns = to_ipc_ns(new);
174 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) || 180 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) ||
175 !ns_capable(current_user_ns(), CAP_SYS_ADMIN)) 181 !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
176 return -EPERM; 182 return -EPERM;
@@ -182,18 +188,10 @@ static int ipcns_install(struct nsproxy *nsproxy, void *new)
182 return 0; 188 return 0;
183} 189}
184 190
185static unsigned int ipcns_inum(void *vp)
186{
187 struct ipc_namespace *ns = vp;
188
189 return ns->proc_inum;
190}
191
192const struct proc_ns_operations ipcns_operations = { 191const struct proc_ns_operations ipcns_operations = {
193 .name = "ipc", 192 .name = "ipc",
194 .type = CLONE_NEWIPC, 193 .type = CLONE_NEWIPC,
195 .get = ipcns_get, 194 .get = ipcns_get,
196 .put = ipcns_put, 195 .put = ipcns_put,
197 .install = ipcns_install, 196 .install = ipcns_install,
198 .inum = ipcns_inum,
199}; 197};
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 9b9a26698144..c17a993a4d2a 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 db95d8eb761b..e1bafe3b47bb 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);
@@ -313,7 +314,12 @@ int reboot_pid_ns(struct pid_namespace *pid_ns, int cmd)
313 return 0; 314 return 0;
314} 315}
315 316
316static void *pidns_get(struct task_struct *task) 317static inline struct pid_namespace *to_pid_ns(struct ns_common *ns)
318{
319 return container_of(ns, struct pid_namespace, ns);
320}
321
322static struct ns_common *pidns_get(struct task_struct *task)
317{ 323{
318 struct pid_namespace *ns; 324 struct pid_namespace *ns;
319 325
@@ -323,18 +329,18 @@ static void *pidns_get(struct task_struct *task)
323 get_pid_ns(ns); 329 get_pid_ns(ns);
324 rcu_read_unlock(); 330 rcu_read_unlock();
325 331
326 return ns; 332 return ns ? &ns->ns : NULL;
327} 333}
328 334
329static void pidns_put(void *ns) 335static void pidns_put(struct ns_common *ns)
330{ 336{
331 put_pid_ns(ns); 337 put_pid_ns(to_pid_ns(ns));
332} 338}
333 339
334static int pidns_install(struct nsproxy *nsproxy, void *ns) 340static int pidns_install(struct nsproxy *nsproxy, struct ns_common *ns)
335{ 341{
336 struct pid_namespace *active = task_active_pid_ns(current); 342 struct pid_namespace *active = task_active_pid_ns(current);
337 struct pid_namespace *ancestor, *new = ns; 343 struct pid_namespace *ancestor, *new = to_pid_ns(ns);
338 344
339 if (!ns_capable(new->user_ns, CAP_SYS_ADMIN) || 345 if (!ns_capable(new->user_ns, CAP_SYS_ADMIN) ||
340 !ns_capable(current_user_ns(), CAP_SYS_ADMIN)) 346 !ns_capable(current_user_ns(), CAP_SYS_ADMIN))
@@ -362,19 +368,12 @@ static int pidns_install(struct nsproxy *nsproxy, void *ns)
362 return 0; 368 return 0;
363} 369}
364 370
365static unsigned int pidns_inum(void *ns)
366{
367 struct pid_namespace *pid_ns = ns;
368 return pid_ns->proc_inum;
369}
370
371const struct proc_ns_operations pidns_operations = { 371const struct proc_ns_operations pidns_operations = {
372 .name = "pid", 372 .name = "pid",
373 .type = CLONE_NEWPID, 373 .type = CLONE_NEWPID,
374 .get = pidns_get, 374 .get = pidns_get,
375 .put = pidns_put, 375 .put = pidns_put,
376 .install = pidns_install, 376 .install = pidns_install,
377 .inum = pidns_inum,
378}; 377};
379 378
380static __init int pid_namespaces_init(void) 379static __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/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