procfs: Move /proc/pid/fd[info] handling code to fd.[ch]
[deliverable/linux.git] / fs / proc / fd.c
CommitLineData
faf60af1
CG
1#include <linux/sched.h>
2#include <linux/errno.h>
3#include <linux/dcache.h>
4#include <linux/path.h>
5#include <linux/fdtable.h>
6#include <linux/namei.h>
7#include <linux/pid.h>
8#include <linux/security.h>
9
10#include <linux/proc_fs.h>
11
12#include "internal.h"
13#include "fd.h"
14
15#define PROC_FDINFO_MAX 64
16
17static int proc_fd_info(struct inode *inode, struct path *path, char *info)
18{
19 struct task_struct *task = get_proc_task(inode);
20 struct files_struct *files = NULL;
21 int fd = proc_fd(inode);
22 struct file *file;
23
24 if (task) {
25 files = get_files_struct(task);
26 put_task_struct(task);
27 }
28 if (files) {
29 /*
30 * We are not taking a ref to the file structure, so we must
31 * hold ->file_lock.
32 */
33 spin_lock(&files->file_lock);
34 file = fcheck_files(files, fd);
35 if (file) {
36 unsigned int f_flags;
37 struct fdtable *fdt;
38
39 fdt = files_fdtable(files);
40 f_flags = file->f_flags & ~O_CLOEXEC;
41 if (close_on_exec(fd, fdt))
42 f_flags |= O_CLOEXEC;
43
44 if (path) {
45 *path = file->f_path;
46 path_get(&file->f_path);
47 }
48 if (info)
49 snprintf(info, PROC_FDINFO_MAX,
50 "pos:\t%lli\n"
51 "flags:\t0%o\n",
52 (long long) file->f_pos,
53 f_flags);
54 spin_unlock(&files->file_lock);
55 put_files_struct(files);
56 return 0;
57 }
58 spin_unlock(&files->file_lock);
59 put_files_struct(files);
60 }
61 return -ENOENT;
62}
63
64static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags)
65{
66 struct files_struct *files;
67 struct task_struct *task;
68 const struct cred *cred;
69 struct inode *inode;
70 int fd;
71
72 if (flags & LOOKUP_RCU)
73 return -ECHILD;
74
75 inode = dentry->d_inode;
76 task = get_proc_task(inode);
77 fd = proc_fd(inode);
78
79 if (task) {
80 files = get_files_struct(task);
81 if (files) {
82 struct file *file;
83
84 rcu_read_lock();
85 file = fcheck_files(files, fd);
86 if (file) {
87 unsigned f_mode = file->f_mode;
88
89 rcu_read_unlock();
90 put_files_struct(files);
91
92 if (task_dumpable(task)) {
93 rcu_read_lock();
94 cred = __task_cred(task);
95 inode->i_uid = cred->euid;
96 inode->i_gid = cred->egid;
97 rcu_read_unlock();
98 } else {
99 inode->i_uid = GLOBAL_ROOT_UID;
100 inode->i_gid = GLOBAL_ROOT_GID;
101 }
102
103 if (S_ISLNK(inode->i_mode)) {
104 unsigned i_mode = S_IFLNK;
105 if (f_mode & FMODE_READ)
106 i_mode |= S_IRUSR | S_IXUSR;
107 if (f_mode & FMODE_WRITE)
108 i_mode |= S_IWUSR | S_IXUSR;
109 inode->i_mode = i_mode;
110 }
111
112 security_task_to_inode(task, inode);
113 put_task_struct(task);
114 return 1;
115 }
116 rcu_read_unlock();
117 put_files_struct(files);
118 }
119 put_task_struct(task);
120 }
121
122 d_drop(dentry);
123 return 0;
124}
125
126static const struct dentry_operations tid_fd_dentry_operations = {
127 .d_revalidate = tid_fd_revalidate,
128 .d_delete = pid_delete_dentry,
129};
130
131static int proc_fd_link(struct dentry *dentry, struct path *path)
132{
133 return proc_fd_info(dentry->d_inode, path, NULL);
134}
135
136static struct dentry *
137proc_fd_instantiate(struct inode *dir, struct dentry *dentry,
138 struct task_struct *task, const void *ptr)
139{
140 struct dentry *error = ERR_PTR(-ENOENT);
141 unsigned fd = (unsigned long)ptr;
142 struct proc_inode *ei;
143 struct inode *inode;
144
145 inode = proc_pid_make_inode(dir->i_sb, task);
146 if (!inode)
147 goto out;
148
149 ei = PROC_I(inode);
150 ei->fd = fd;
151
152 inode->i_mode = S_IFLNK;
153 inode->i_op = &proc_pid_link_inode_operations;
154 inode->i_size = 64;
155
156 ei->op.proc_get_link = proc_fd_link;
157
158 d_set_d_op(dentry, &tid_fd_dentry_operations);
159 d_add(dentry, inode);
160
161 /* Close the race of the process dying before we return the dentry */
162 if (tid_fd_revalidate(dentry, 0))
163 error = NULL;
164 out:
165 return error;
166}
167
168static struct dentry *proc_lookupfd_common(struct inode *dir,
169 struct dentry *dentry,
170 instantiate_t instantiate)
171{
172 struct task_struct *task = get_proc_task(dir);
173 struct dentry *result = ERR_PTR(-ENOENT);
174 unsigned fd = name_to_int(dentry);
175
176 if (!task)
177 goto out_no_task;
178 if (fd == ~0U)
179 goto out;
180
181 result = instantiate(dir, dentry, task, (void *)(unsigned long)fd);
182out:
183 put_task_struct(task);
184out_no_task:
185 return result;
186}
187
188static int proc_readfd_common(struct file * filp, void * dirent,
189 filldir_t filldir, instantiate_t instantiate)
190{
191 struct dentry *dentry = filp->f_path.dentry;
192 struct inode *inode = dentry->d_inode;
193 struct task_struct *p = get_proc_task(inode);
194 struct files_struct *files;
195 unsigned int fd, ino;
196 int retval;
197
198 retval = -ENOENT;
199 if (!p)
200 goto out_no_task;
201 retval = 0;
202
203 fd = filp->f_pos;
204 switch (fd) {
205 case 0:
206 if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0)
207 goto out;
208 filp->f_pos++;
209 case 1:
210 ino = parent_ino(dentry);
211 if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0)
212 goto out;
213 filp->f_pos++;
214 default:
215 files = get_files_struct(p);
216 if (!files)
217 goto out;
218 rcu_read_lock();
219 for (fd = filp->f_pos - 2;
220 fd < files_fdtable(files)->max_fds;
221 fd++, filp->f_pos++) {
222 char name[PROC_NUMBUF];
223 int len;
224 int rv;
225
226 if (!fcheck_files(files, fd))
227 continue;
228 rcu_read_unlock();
229
230 len = snprintf(name, sizeof(name), "%d", fd);
231 rv = proc_fill_cache(filp, dirent, filldir,
232 name, len, instantiate, p,
233 (void *)(unsigned long)fd);
234 if (rv < 0)
235 goto out_fd_loop;
236 rcu_read_lock();
237 }
238 rcu_read_unlock();
239out_fd_loop:
240 put_files_struct(files);
241 }
242out:
243 put_task_struct(p);
244out_no_task:
245 return retval;
246}
247
248static ssize_t proc_fdinfo_read(struct file *file, char __user *buf,
249 size_t len, loff_t *ppos)
250{
251 char tmp[PROC_FDINFO_MAX];
252 int err = proc_fd_info(file->f_path.dentry->d_inode, NULL, tmp);
253 if (!err)
254 err = simple_read_from_buffer(buf, len, ppos, tmp, strlen(tmp));
255 return err;
256}
257
258static const struct file_operations proc_fdinfo_file_operations = {
259 .open = nonseekable_open,
260 .read = proc_fdinfo_read,
261 .llseek = no_llseek,
262};
263
264static int proc_readfd(struct file *filp, void *dirent, filldir_t filldir)
265{
266 return proc_readfd_common(filp, dirent, filldir, proc_fd_instantiate);
267}
268
269const struct file_operations proc_fd_operations = {
270 .read = generic_read_dir,
271 .readdir = proc_readfd,
272 .llseek = default_llseek,
273};
274
275static struct dentry *proc_lookupfd(struct inode *dir, struct dentry *dentry,
276 unsigned int flags)
277{
278 return proc_lookupfd_common(dir, dentry, proc_fd_instantiate);
279}
280
281/*
282 * /proc/pid/fd needs a special permission handler so that a process can still
283 * access /proc/self/fd after it has executed a setuid().
284 */
285int proc_fd_permission(struct inode *inode, int mask)
286{
287 int rv = generic_permission(inode, mask);
288 if (rv == 0)
289 return 0;
290 if (task_pid(current) == proc_pid(inode))
291 rv = 0;
292 return rv;
293}
294
295const struct inode_operations proc_fd_inode_operations = {
296 .lookup = proc_lookupfd,
297 .permission = proc_fd_permission,
298 .setattr = proc_setattr,
299};
300
301static struct dentry *
302proc_fdinfo_instantiate(struct inode *dir, struct dentry *dentry,
303 struct task_struct *task, const void *ptr)
304{
305 struct dentry *error = ERR_PTR(-ENOENT);
306 unsigned fd = (unsigned long)ptr;
307 struct proc_inode *ei;
308 struct inode *inode;
309
310 inode = proc_pid_make_inode(dir->i_sb, task);
311 if (!inode)
312 goto out;
313
314 ei = PROC_I(inode);
315 ei->fd = fd;
316
317 inode->i_mode = S_IFREG | S_IRUSR;
318 inode->i_fop = &proc_fdinfo_file_operations;
319
320 d_set_d_op(dentry, &tid_fd_dentry_operations);
321 d_add(dentry, inode);
322
323 /* Close the race of the process dying before we return the dentry */
324 if (tid_fd_revalidate(dentry, 0))
325 error = NULL;
326 out:
327 return error;
328}
329
330static struct dentry *
331proc_lookupfdinfo(struct inode *dir, struct dentry *dentry, unsigned int flags)
332{
333 return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate);
334}
335
336static int proc_readfdinfo(struct file *filp, void *dirent, filldir_t filldir)
337{
338 return proc_readfd_common(filp, dirent, filldir,
339 proc_fdinfo_instantiate);
340}
341
342const struct inode_operations proc_fdinfo_inode_operations = {
343 .lookup = proc_lookupfdinfo,
344 .setattr = proc_setattr,
345};
346
347const struct file_operations proc_fdinfo_operations = {
348 .read = generic_read_dir,
349 .readdir = proc_readfdinfo,
350 .llseek = default_llseek,
351};
This page took 0.036552 seconds and 5 git commands to generate.