]> git.karo-electronics.de Git - karo-tx-linux.git/blob - fs/proc/fd.c
procfs: Move /proc/pid/fd[info] handling code to fd.[ch]
[karo-tx-linux.git] / fs / proc / fd.c
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
17 static 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
64 static 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
126 static const struct dentry_operations tid_fd_dentry_operations = {
127         .d_revalidate   = tid_fd_revalidate,
128         .d_delete       = pid_delete_dentry,
129 };
130
131 static int proc_fd_link(struct dentry *dentry, struct path *path)
132 {
133         return proc_fd_info(dentry->d_inode, path, NULL);
134 }
135
136 static struct dentry *
137 proc_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
168 static 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);
182 out:
183         put_task_struct(task);
184 out_no_task:
185         return result;
186 }
187
188 static 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();
239 out_fd_loop:
240                         put_files_struct(files);
241         }
242 out:
243         put_task_struct(p);
244 out_no_task:
245         return retval;
246 }
247
248 static 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
258 static const struct file_operations proc_fdinfo_file_operations = {
259         .open           = nonseekable_open,
260         .read           = proc_fdinfo_read,
261         .llseek         = no_llseek,
262 };
263
264 static 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
269 const struct file_operations proc_fd_operations = {
270         .read           = generic_read_dir,
271         .readdir        = proc_readfd,
272         .llseek         = default_llseek,
273 };
274
275 static 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  */
285 int 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
295 const struct inode_operations proc_fd_inode_operations = {
296         .lookup         = proc_lookupfd,
297         .permission     = proc_fd_permission,
298         .setattr        = proc_setattr,
299 };
300
301 static struct dentry *
302 proc_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
330 static struct dentry *
331 proc_lookupfdinfo(struct inode *dir, struct dentry *dentry, unsigned int flags)
332 {
333         return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate);
334 }
335
336 static 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
342 const struct inode_operations proc_fdinfo_inode_operations = {
343         .lookup         = proc_lookupfdinfo,
344         .setattr        = proc_setattr,
345 };
346
347 const struct file_operations proc_fdinfo_operations = {
348         .read           = generic_read_dir,
349         .readdir        = proc_readfdinfo,
350         .llseek         = default_llseek,
351 };