Add linux-next specific files for 20110831
[linux-2.6/next.git] / fs / proc / namespaces.c
blob53d4cc890aa4939c44dfb6ce898800da49ee8a82
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/mnt_namespace.h>
13 #include <linux/ipc_namespace.h>
14 #include <linux/pid_namespace.h>
15 #include "internal.h"
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
30 static const struct file_operations ns_file_operations = {
31 .llseek = no_llseek,
34 static const struct inode_operations ns_inode_operations = {
35 .setattr = proc_setattr,
38 static int ns_delete_dentry(const struct dentry *dentry)
40 /* Don't cache namespace dentries when not in use */
41 return 1;
44 static char *ns_dname(struct dentry *dentry, char *buffer, int buflen)
46 struct inode *inode = dentry->d_inode;
47 const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops;
49 return dynamic_dname(dentry, buffer, buflen, "%s:[%lu]",
50 ns_ops->name, inode->i_ino);
53 static const struct dentry_operations ns_dentry_operations =
55 .d_delete = ns_delete_dentry,
56 .d_dname = ns_dname,
59 static struct dentry *proc_ns_get_dentry(struct super_block *sb,
60 struct task_struct *task, const struct proc_ns_operations *ns_ops)
62 struct dentry *dentry;
63 struct inode *inode;
64 struct proc_inode *ei;
65 struct qstr qname = { .name = "", };
66 void *ns;
68 ns = ns_ops->get(task);
69 if (!ns)
70 return ERR_PTR(-ENOENT);
72 dentry = d_alloc_pseudo(sb, &qname);
73 if (!dentry) {
74 ns_ops->put(ns);
75 return ERR_PTR(-ENOMEM);
78 inode = new_inode(sb);
79 if (!inode) {
80 dput(dentry);
81 ns_ops->put(ns);
82 return ERR_PTR(-ENOMEM);
85 ei = PROC_I(inode);
86 inode->i_ino = get_next_ino();
87 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
88 inode->i_op = &ns_inode_operations;
89 inode->i_mode = S_IFREG|S_IRUSR;
90 inode->i_fop = &ns_file_operations;
91 ei->ns_ops = ns_ops;
92 ei->ns = ns;
94 d_set_d_op(dentry, &ns_dentry_operations);
95 d_instantiate(dentry, inode);
97 return dentry;
100 static void *proc_ns_follow_link(struct dentry *dentry, struct nameidata *nd)
102 struct inode *inode = dentry->d_inode;
103 struct super_block *sb = inode->i_sb;
104 struct proc_inode *ei = PROC_I(inode);
105 struct task_struct *task;
106 struct dentry *ns_dentry;
107 void *error = ERR_PTR(-EACCES);
109 task = get_proc_task(inode);
110 if (!task)
111 goto out;
113 if (!ptrace_may_access(task, PTRACE_MODE_READ))
114 goto out_put_task;
116 ns_dentry = proc_ns_get_dentry(sb, task, ei->ns_ops);
117 if (IS_ERR(ns_dentry)) {
118 error = ERR_CAST(ns_dentry);
119 goto out_put_task;
122 dput(nd->path.dentry);
123 nd->path.dentry = ns_dentry;
124 error = NULL;
126 out_put_task:
127 put_task_struct(task);
128 out:
129 return error;
132 static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int buflen)
134 struct inode *inode = dentry->d_inode;
135 struct proc_inode *ei = PROC_I(inode);
136 const struct proc_ns_operations *ns_ops = ei->ns_ops;
137 struct task_struct *task;
138 char name[50];
139 int len = -EACCES;
141 task = get_proc_task(inode);
142 if (!task)
143 goto out;
145 if (!ptrace_may_access(task, PTRACE_MODE_READ))
146 goto out_put_task;
148 snprintf(name, sizeof(name), "%s", ns_ops->name);
149 len = strlen(name);
151 if (len > buflen)
152 len = buflen;
153 if (copy_to_user(buffer, ns_ops->name, len))
154 len = -EFAULT;
156 out_put_task:
157 put_task_struct(task);
158 out:
159 return len;
162 static const struct inode_operations proc_ns_link_inode_operations = {
163 .readlink = proc_ns_readlink,
164 .follow_link = proc_ns_follow_link,
165 .setattr = proc_setattr,
168 static struct dentry *proc_ns_instantiate(struct inode *dir,
169 struct dentry *dentry, struct task_struct *task, const void *ptr)
171 const struct proc_ns_operations *ns_ops = ptr;
172 struct inode *inode;
173 struct proc_inode *ei;
174 struct dentry *error = ERR_PTR(-ENOENT);
176 inode = proc_pid_make_inode(dir->i_sb, task);
177 if (!inode)
178 goto out;
180 ei = PROC_I(inode);
181 inode->i_mode = S_IFLNK|S_IRWXUGO;
182 inode->i_op = &proc_ns_link_inode_operations;
183 ei->ns_ops = ns_ops;
185 d_set_d_op(dentry, &pid_dentry_operations);
186 d_add(dentry, inode);
187 /* Close the race of the process dying before we return the dentry */
188 if (pid_revalidate(dentry, NULL))
189 error = NULL;
190 out:
191 return error;
194 static int proc_ns_fill_cache(struct file *filp, void *dirent,
195 filldir_t filldir, struct task_struct *task,
196 const struct proc_ns_operations *ops)
198 return proc_fill_cache(filp, dirent, filldir,
199 ops->name, strlen(ops->name),
200 proc_ns_instantiate, task, ops);
203 static int proc_ns_dir_readdir(struct file *filp, void *dirent,
204 filldir_t filldir)
206 int i;
207 struct dentry *dentry = filp->f_path.dentry;
208 struct inode *inode = dentry->d_inode;
209 struct task_struct *task = get_proc_task(inode);
210 const struct proc_ns_operations **entry, **last;
211 ino_t ino;
212 int ret;
214 ret = -ENOENT;
215 if (!task)
216 goto out_no_task;
218 ret = 0;
219 i = filp->f_pos;
220 switch (i) {
221 case 0:
222 ino = inode->i_ino;
223 if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
224 goto out;
225 i++;
226 filp->f_pos++;
227 /* fall through */
228 case 1:
229 ino = parent_ino(dentry);
230 if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
231 goto out;
232 i++;
233 filp->f_pos++;
234 /* fall through */
235 default:
236 i -= 2;
237 if (i >= ARRAY_SIZE(ns_entries)) {
238 ret = 1;
239 goto out;
241 entry = ns_entries + i;
242 last = &ns_entries[ARRAY_SIZE(ns_entries) - 1];
243 while (entry <= last) {
244 if (proc_ns_fill_cache(filp, dirent, filldir,
245 task, *entry) < 0)
246 goto out;
247 filp->f_pos++;
248 entry++;
252 ret = 1;
253 out:
254 put_task_struct(task);
255 out_no_task:
256 return ret;
259 const struct file_operations proc_ns_dir_operations = {
260 .read = generic_read_dir,
261 .readdir = proc_ns_dir_readdir,
264 static struct dentry *proc_ns_dir_lookup(struct inode *dir,
265 struct dentry *dentry, struct nameidata *nd)
267 struct dentry *error;
268 struct task_struct *task = get_proc_task(dir);
269 const struct proc_ns_operations **entry, **last;
270 unsigned int len = dentry->d_name.len;
272 error = ERR_PTR(-ENOENT);
274 if (!task)
275 goto out_no_task;
277 last = &ns_entries[ARRAY_SIZE(ns_entries) - 1];
278 for (entry = ns_entries; entry <= last; entry++) {
279 if (strlen((*entry)->name) != len)
280 continue;
281 if (!memcmp(dentry->d_name.name, (*entry)->name, len))
282 break;
284 if (entry > last)
285 goto out;
287 error = proc_ns_instantiate(dir, dentry, task, *entry);
288 out:
289 put_task_struct(task);
290 out_no_task:
291 return error;
294 const struct inode_operations proc_ns_dir_inode_operations = {
295 .lookup = proc_ns_dir_lookup,
296 .getattr = pid_getattr,
297 .setattr = proc_setattr,
300 struct file *proc_ns_fget(int fd)
302 struct file *file;
304 file = fget(fd);
305 if (!file)
306 return ERR_PTR(-EBADF);
308 if (file->f_op != &ns_file_operations)
309 goto out_invalid;
311 return file;
313 out_invalid:
314 fput(file);
315 return ERR_PTR(-EINVAL);