~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/proc/fd.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 #include <linux/sched/signal.h>
  3 #include <linux/errno.h>
  4 #include <linux/dcache.h>
  5 #include <linux/path.h>
  6 #include <linux/fdtable.h>
  7 #include <linux/namei.h>
  8 #include <linux/pid.h>
  9 #include <linux/ptrace.h>
 10 #include <linux/bitmap.h>
 11 #include <linux/security.h>
 12 #include <linux/file.h>
 13 #include <linux/seq_file.h>
 14 #include <linux/fs.h>
 15 #include <linux/filelock.h>
 16 
 17 #include <linux/proc_fs.h>
 18 
 19 #include "../mount.h"
 20 #include "internal.h"
 21 #include "fd.h"
 22 
 23 static int seq_show(struct seq_file *m, void *v)
 24 {
 25         struct files_struct *files = NULL;
 26         int f_flags = 0, ret = -ENOENT;
 27         struct file *file = NULL;
 28         struct task_struct *task;
 29 
 30         task = get_proc_task(m->private);
 31         if (!task)
 32                 return -ENOENT;
 33 
 34         task_lock(task);
 35         files = task->files;
 36         if (files) {
 37                 unsigned int fd = proc_fd(m->private);
 38 
 39                 spin_lock(&files->file_lock);
 40                 file = files_lookup_fd_locked(files, fd);
 41                 if (file) {
 42                         f_flags = file->f_flags;
 43                         if (close_on_exec(fd, files))
 44                                 f_flags |= O_CLOEXEC;
 45 
 46                         get_file(file);
 47                         ret = 0;
 48                 }
 49                 spin_unlock(&files->file_lock);
 50         }
 51         task_unlock(task);
 52         put_task_struct(task);
 53 
 54         if (ret)
 55                 return ret;
 56 
 57         seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\nino:\t%lu\n",
 58                    (long long)file->f_pos, f_flags,
 59                    real_mount(file->f_path.mnt)->mnt_id,
 60                    file_inode(file)->i_ino);
 61 
 62         /* show_fd_locks() never deferences files so a stale value is safe */
 63         show_fd_locks(m, file, files);
 64         if (seq_has_overflowed(m))
 65                 goto out;
 66 
 67         if (file->f_op->show_fdinfo)
 68                 file->f_op->show_fdinfo(m, file);
 69 
 70 out:
 71         fput(file);
 72         return 0;
 73 }
 74 
 75 static int seq_fdinfo_open(struct inode *inode, struct file *file)
 76 {
 77         return single_open(file, seq_show, inode);
 78 }
 79 
 80 /**
 81  * Shared /proc/pid/fdinfo and /proc/pid/fdinfo/fd permission helper to ensure
 82  * that the current task has PTRACE_MODE_READ in addition to the normal
 83  * POSIX-like checks.
 84  */
 85 static int proc_fdinfo_permission(struct mnt_idmap *idmap, struct inode *inode,
 86                                   int mask)
 87 {
 88         bool allowed = false;
 89         struct task_struct *task = get_proc_task(inode);
 90 
 91         if (!task)
 92                 return -ESRCH;
 93 
 94         allowed = ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS);
 95         put_task_struct(task);
 96 
 97         if (!allowed)
 98                 return -EACCES;
 99 
100         return generic_permission(idmap, inode, mask);
101 }
102 
103 static const struct inode_operations proc_fdinfo_file_inode_operations = {
104         .permission     = proc_fdinfo_permission,
105         .setattr        = proc_setattr,
106 };
107 
108 static const struct file_operations proc_fdinfo_file_operations = {
109         .open           = seq_fdinfo_open,
110         .read           = seq_read,
111         .llseek         = seq_lseek,
112         .release        = single_release,
113 };
114 
115 static bool tid_fd_mode(struct task_struct *task, unsigned fd, fmode_t *mode)
116 {
117         struct file *file;
118 
119         rcu_read_lock();
120         file = task_lookup_fdget_rcu(task, fd);
121         rcu_read_unlock();
122         if (file) {
123                 *mode = file->f_mode;
124                 fput(file);
125         }
126         return !!file;
127 }
128 
129 static void tid_fd_update_inode(struct task_struct *task, struct inode *inode,
130                                 fmode_t f_mode)
131 {
132         task_dump_owner(task, 0, &inode->i_uid, &inode->i_gid);
133 
134         if (S_ISLNK(inode->i_mode)) {
135                 unsigned i_mode = S_IFLNK;
136                 if (f_mode & FMODE_READ)
137                         i_mode |= S_IRUSR | S_IXUSR;
138                 if (f_mode & FMODE_WRITE)
139                         i_mode |= S_IWUSR | S_IXUSR;
140                 inode->i_mode = i_mode;
141         }
142         security_task_to_inode(task, inode);
143 }
144 
145 static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags)
146 {
147         struct task_struct *task;
148         struct inode *inode;
149         unsigned int fd;
150 
151         if (flags & LOOKUP_RCU)
152                 return -ECHILD;
153 
154         inode = d_inode(dentry);
155         task = get_proc_task(inode);
156         fd = proc_fd(inode);
157 
158         if (task) {
159                 fmode_t f_mode;
160                 if (tid_fd_mode(task, fd, &f_mode)) {
161                         tid_fd_update_inode(task, inode, f_mode);
162                         put_task_struct(task);
163                         return 1;
164                 }
165                 put_task_struct(task);
166         }
167         return 0;
168 }
169 
170 static const struct dentry_operations tid_fd_dentry_operations = {
171         .d_revalidate   = tid_fd_revalidate,
172         .d_delete       = pid_delete_dentry,
173 };
174 
175 static int proc_fd_link(struct dentry *dentry, struct path *path)
176 {
177         struct task_struct *task;
178         int ret = -ENOENT;
179 
180         task = get_proc_task(d_inode(dentry));
181         if (task) {
182                 unsigned int fd = proc_fd(d_inode(dentry));
183                 struct file *fd_file;
184 
185                 fd_file = fget_task(task, fd);
186                 if (fd_file) {
187                         *path = fd_file->f_path;
188                         path_get(&fd_file->f_path);
189                         ret = 0;
190                         fput(fd_file);
191                 }
192                 put_task_struct(task);
193         }
194 
195         return ret;
196 }
197 
198 struct fd_data {
199         fmode_t mode;
200         unsigned fd;
201 };
202 
203 static struct dentry *proc_fd_instantiate(struct dentry *dentry,
204         struct task_struct *task, const void *ptr)
205 {
206         const struct fd_data *data = ptr;
207         struct proc_inode *ei;
208         struct inode *inode;
209 
210         inode = proc_pid_make_inode(dentry->d_sb, task, S_IFLNK);
211         if (!inode)
212                 return ERR_PTR(-ENOENT);
213 
214         ei = PROC_I(inode);
215         ei->fd = data->fd;
216 
217         inode->i_op = &proc_pid_link_inode_operations;
218         inode->i_size = 64;
219 
220         ei->op.proc_get_link = proc_fd_link;
221         tid_fd_update_inode(task, inode, data->mode);
222 
223         d_set_d_op(dentry, &tid_fd_dentry_operations);
224         return d_splice_alias(inode, dentry);
225 }
226 
227 static struct dentry *proc_lookupfd_common(struct inode *dir,
228                                            struct dentry *dentry,
229                                            instantiate_t instantiate)
230 {
231         struct task_struct *task = get_proc_task(dir);
232         struct fd_data data = {.fd = name_to_int(&dentry->d_name)};
233         struct dentry *result = ERR_PTR(-ENOENT);
234 
235         if (!task)
236                 goto out_no_task;
237         if (data.fd == ~0U)
238                 goto out;
239         if (!tid_fd_mode(task, data.fd, &data.mode))
240                 goto out;
241 
242         result = instantiate(dentry, task, &data);
243 out:
244         put_task_struct(task);
245 out_no_task:
246         return result;
247 }
248 
249 static int proc_readfd_common(struct file *file, struct dir_context *ctx,
250                               instantiate_t instantiate)
251 {
252         struct task_struct *p = get_proc_task(file_inode(file));
253         unsigned int fd;
254 
255         if (!p)
256                 return -ENOENT;
257 
258         if (!dir_emit_dots(file, ctx))
259                 goto out;
260 
261         rcu_read_lock();
262         for (fd = ctx->pos - 2;; fd++) {
263                 struct file *f;
264                 struct fd_data data;
265                 char name[10 + 1];
266                 unsigned int len;
267 
268                 f = task_lookup_next_fdget_rcu(p, &fd);
269                 ctx->pos = fd + 2LL;
270                 if (!f)
271                         break;
272                 data.mode = f->f_mode;
273                 rcu_read_unlock();
274                 fput(f);
275                 data.fd = fd;
276 
277                 len = snprintf(name, sizeof(name), "%u", fd);
278                 if (!proc_fill_cache(file, ctx,
279                                      name, len, instantiate, p,
280                                      &data))
281                         goto out;
282                 cond_resched();
283                 rcu_read_lock();
284         }
285         rcu_read_unlock();
286 out:
287         put_task_struct(p);
288         return 0;
289 }
290 
291 static int proc_readfd_count(struct inode *inode, loff_t *count)
292 {
293         struct task_struct *p = get_proc_task(inode);
294         struct fdtable *fdt;
295 
296         if (!p)
297                 return -ENOENT;
298 
299         task_lock(p);
300         if (p->files) {
301                 rcu_read_lock();
302 
303                 fdt = files_fdtable(p->files);
304                 *count = bitmap_weight(fdt->open_fds, fdt->max_fds);
305 
306                 rcu_read_unlock();
307         }
308         task_unlock(p);
309 
310         put_task_struct(p);
311 
312         return 0;
313 }
314 
315 static int proc_readfd(struct file *file, struct dir_context *ctx)
316 {
317         return proc_readfd_common(file, ctx, proc_fd_instantiate);
318 }
319 
320 const struct file_operations proc_fd_operations = {
321         .read           = generic_read_dir,
322         .iterate_shared = proc_readfd,
323         .llseek         = generic_file_llseek,
324 };
325 
326 static struct dentry *proc_lookupfd(struct inode *dir, struct dentry *dentry,
327                                     unsigned int flags)
328 {
329         return proc_lookupfd_common(dir, dentry, proc_fd_instantiate);
330 }
331 
332 /*
333  * /proc/pid/fd needs a special permission handler so that a process can still
334  * access /proc/self/fd after it has executed a setuid().
335  */
336 int proc_fd_permission(struct mnt_idmap *idmap,
337                        struct inode *inode, int mask)
338 {
339         struct task_struct *p;
340         int rv;
341 
342         rv = generic_permission(&nop_mnt_idmap, inode, mask);
343         if (rv == 0)
344                 return rv;
345 
346         rcu_read_lock();
347         p = pid_task(proc_pid(inode), PIDTYPE_PID);
348         if (p && same_thread_group(p, current))
349                 rv = 0;
350         rcu_read_unlock();
351 
352         return rv;
353 }
354 
355 static int proc_fd_getattr(struct mnt_idmap *idmap,
356                         const struct path *path, struct kstat *stat,
357                         u32 request_mask, unsigned int query_flags)
358 {
359         struct inode *inode = d_inode(path->dentry);
360         int rv = 0;
361 
362         generic_fillattr(&nop_mnt_idmap, request_mask, inode, stat);
363 
364         /* If it's a directory, put the number of open fds there */
365         if (S_ISDIR(inode->i_mode)) {
366                 rv = proc_readfd_count(inode, &stat->size);
367                 if (rv < 0)
368                         return rv;
369         }
370 
371         return rv;
372 }
373 
374 const struct inode_operations proc_fd_inode_operations = {
375         .lookup         = proc_lookupfd,
376         .permission     = proc_fd_permission,
377         .getattr        = proc_fd_getattr,
378         .setattr        = proc_setattr,
379 };
380 
381 static struct dentry *proc_fdinfo_instantiate(struct dentry *dentry,
382         struct task_struct *task, const void *ptr)
383 {
384         const struct fd_data *data = ptr;
385         struct proc_inode *ei;
386         struct inode *inode;
387 
388         inode = proc_pid_make_inode(dentry->d_sb, task, S_IFREG | S_IRUGO);
389         if (!inode)
390                 return ERR_PTR(-ENOENT);
391 
392         ei = PROC_I(inode);
393         ei->fd = data->fd;
394 
395         inode->i_op = &proc_fdinfo_file_inode_operations;
396 
397         inode->i_fop = &proc_fdinfo_file_operations;
398         tid_fd_update_inode(task, inode, 0);
399 
400         d_set_d_op(dentry, &tid_fd_dentry_operations);
401         return d_splice_alias(inode, dentry);
402 }
403 
404 static struct dentry *
405 proc_lookupfdinfo(struct inode *dir, struct dentry *dentry, unsigned int flags)
406 {
407         return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate);
408 }
409 
410 static int proc_readfdinfo(struct file *file, struct dir_context *ctx)
411 {
412         return proc_readfd_common(file, ctx,
413                                   proc_fdinfo_instantiate);
414 }
415 
416 const struct inode_operations proc_fdinfo_inode_operations = {
417         .lookup         = proc_lookupfdinfo,
418         .permission     = proc_fdinfo_permission,
419         .setattr        = proc_setattr,
420 };
421 
422 const struct file_operations proc_fdinfo_operations = {
423         .read           = generic_read_dir,
424         .iterate_shared = proc_readfdinfo,
425         .llseek         = generic_file_llseek,
426 };
427 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php