]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - fs/proc/namespaces.c
bury struct proc_ns in fs/proc
[mirror_ubuntu-artful-kernel.git] / fs / proc / namespaces.c
1 #include <linux/proc_fs.h>
2 #include <linux/nsproxy.h>
3 #include <linux/sched.h>
4 #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>
9 #include <linux/file.h>
10 #include <linux/utsname.h>
11 #include <net/net_namespace.h>
12 #include <linux/ipc_namespace.h>
13 #include <linux/pid_namespace.h>
14 #include <linux/user_namespace.h>
15 #include "internal.h"
16
17
18 static const struct proc_ns_operations *ns_entries[] = {
19 #ifdef CONFIG_NET_NS
20 &netns_operations,
21 #endif
22 #ifdef CONFIG_UTS_NS
23 &utsns_operations,
24 #endif
25 #ifdef CONFIG_IPC_NS
26 &ipcns_operations,
27 #endif
28 #ifdef CONFIG_PID_NS
29 &pidns_operations,
30 #endif
31 #ifdef CONFIG_USER_NS
32 &userns_operations,
33 #endif
34 &mntns_operations,
35 };
36
37 static const struct file_operations ns_file_operations = {
38 .llseek = no_llseek,
39 };
40
41 static const struct inode_operations ns_inode_operations = {
42 .setattr = proc_setattr,
43 };
44
45 static 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 = dentry->d_fsdata;
49
50 return dynamic_dname(dentry, buffer, buflen, "%s:[%lu]",
51 ns_ops->name, inode->i_ino);
52 }
53
54 const struct dentry_operations ns_dentry_operations =
55 {
56 .d_delete = always_delete_dentry,
57 .d_dname = ns_dname,
58 };
59
60 static 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 struct ns_common *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 dentry->d_fsdata = (void *)ns_ops;
79
80 inode = iget_locked(sb, ns->inum);
81 if (!inode) {
82 dput(dentry);
83 ns_ops->put(ns);
84 return ERR_PTR(-ENOMEM);
85 }
86
87 ei = PROC_I(inode);
88 if (inode->i_state & I_NEW) {
89 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
90 inode->i_op = &ns_inode_operations;
91 inode->i_mode = S_IFREG | S_IRUGO;
92 inode->i_fop = &ns_file_operations;
93 ei->ns.ns_ops = ns_ops;
94 ei->ns.ns = ns;
95 unlock_new_inode(inode);
96 } else {
97 ns_ops->put(ns);
98 }
99
100 d_set_d_op(dentry, &ns_dentry_operations);
101 result = d_instantiate_unique(dentry, inode);
102 if (result) {
103 dput(dentry);
104 dentry = result;
105 }
106
107 return dentry;
108 }
109
110 static void *proc_ns_follow_link(struct dentry *dentry, struct nameidata *nd)
111 {
112 struct inode *inode = dentry->d_inode;
113 struct super_block *sb = inode->i_sb;
114 struct proc_inode *ei = PROC_I(inode);
115 struct task_struct *task;
116 struct path ns_path;
117 void *error = ERR_PTR(-EACCES);
118
119 task = get_proc_task(inode);
120 if (!task)
121 goto out;
122
123 if (!ptrace_may_access(task, PTRACE_MODE_READ))
124 goto out_put_task;
125
126 ns_path.dentry = proc_ns_get_dentry(sb, task, ei->ns.ns_ops);
127 if (IS_ERR(ns_path.dentry)) {
128 error = ERR_CAST(ns_path.dentry);
129 goto out_put_task;
130 }
131
132 ns_path.mnt = mntget(nd->path.mnt);
133 nd_jump_link(nd, &ns_path);
134 error = NULL;
135
136 out_put_task:
137 put_task_struct(task);
138 out:
139 return error;
140 }
141
142 static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int buflen)
143 {
144 struct inode *inode = dentry->d_inode;
145 struct proc_inode *ei = PROC_I(inode);
146 const struct proc_ns_operations *ns_ops = ei->ns.ns_ops;
147 struct task_struct *task;
148 struct ns_common *ns;
149 char name[50];
150 int res = -EACCES;
151
152 task = get_proc_task(inode);
153 if (!task)
154 goto out;
155
156 if (!ptrace_may_access(task, PTRACE_MODE_READ))
157 goto out_put_task;
158
159 res = -ENOENT;
160 ns = ns_ops->get(task);
161 if (!ns)
162 goto out_put_task;
163
164 snprintf(name, sizeof(name), "%s:[%u]", ns_ops->name, ns->inum);
165 res = readlink_copy(buffer, buflen, name);
166 ns_ops->put(ns);
167 out_put_task:
168 put_task_struct(task);
169 out:
170 return res;
171 }
172
173 static const struct inode_operations proc_ns_link_inode_operations = {
174 .readlink = proc_ns_readlink,
175 .follow_link = proc_ns_follow_link,
176 .setattr = proc_setattr,
177 };
178
179 static int proc_ns_instantiate(struct inode *dir,
180 struct dentry *dentry, struct task_struct *task, const void *ptr)
181 {
182 const struct proc_ns_operations *ns_ops = ptr;
183 struct inode *inode;
184 struct proc_inode *ei;
185
186 inode = proc_pid_make_inode(dir->i_sb, task);
187 if (!inode)
188 goto out;
189
190 ei = PROC_I(inode);
191 inode->i_mode = S_IFLNK|S_IRWXUGO;
192 inode->i_op = &proc_ns_link_inode_operations;
193 ei->ns.ns_ops = ns_ops;
194
195 d_set_d_op(dentry, &pid_dentry_operations);
196 d_add(dentry, inode);
197 /* Close the race of the process dying before we return the dentry */
198 if (pid_revalidate(dentry, 0))
199 return 0;
200 out:
201 return -ENOENT;
202 }
203
204 static int proc_ns_dir_readdir(struct file *file, struct dir_context *ctx)
205 {
206 struct task_struct *task = get_proc_task(file_inode(file));
207 const struct proc_ns_operations **entry, **last;
208
209 if (!task)
210 return -ENOENT;
211
212 if (!dir_emit_dots(file, ctx))
213 goto out;
214 if (ctx->pos >= 2 + ARRAY_SIZE(ns_entries))
215 goto out;
216 entry = ns_entries + (ctx->pos - 2);
217 last = &ns_entries[ARRAY_SIZE(ns_entries) - 1];
218 while (entry <= last) {
219 const struct proc_ns_operations *ops = *entry;
220 if (!proc_fill_cache(file, ctx, ops->name, strlen(ops->name),
221 proc_ns_instantiate, task, ops))
222 break;
223 ctx->pos++;
224 entry++;
225 }
226 out:
227 put_task_struct(task);
228 return 0;
229 }
230
231 const struct file_operations proc_ns_dir_operations = {
232 .read = generic_read_dir,
233 .iterate = proc_ns_dir_readdir,
234 };
235
236 static struct dentry *proc_ns_dir_lookup(struct inode *dir,
237 struct dentry *dentry, unsigned int flags)
238 {
239 int error;
240 struct task_struct *task = get_proc_task(dir);
241 const struct proc_ns_operations **entry, **last;
242 unsigned int len = dentry->d_name.len;
243
244 error = -ENOENT;
245
246 if (!task)
247 goto out_no_task;
248
249 last = &ns_entries[ARRAY_SIZE(ns_entries)];
250 for (entry = ns_entries; entry < last; entry++) {
251 if (strlen((*entry)->name) != len)
252 continue;
253 if (!memcmp(dentry->d_name.name, (*entry)->name, len))
254 break;
255 }
256 if (entry == last)
257 goto out;
258
259 error = proc_ns_instantiate(dir, dentry, task, *entry);
260 out:
261 put_task_struct(task);
262 out_no_task:
263 return ERR_PTR(error);
264 }
265
266 const struct inode_operations proc_ns_dir_inode_operations = {
267 .lookup = proc_ns_dir_lookup,
268 .getattr = pid_getattr,
269 .setattr = proc_setattr,
270 };
271
272 struct file *proc_ns_fget(int fd)
273 {
274 struct file *file;
275
276 file = fget(fd);
277 if (!file)
278 return ERR_PTR(-EBADF);
279
280 if (file->f_op != &ns_file_operations)
281 goto out_invalid;
282
283 return file;
284
285 out_invalid:
286 fput(file);
287 return ERR_PTR(-EINVAL);
288 }
289
290 struct ns_common *get_proc_ns(struct inode *inode)
291 {
292 return PROC_I(inode)->ns.ns;
293 }
294
295 bool proc_ns_inode(struct inode *inode)
296 {
297 return inode->i_fop == &ns_file_operations;
298 }