LCOV - code coverage report
Current view: top level - fs/proc - fd.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 161 0.0 %
Date: 2023-07-19 18:55:55 Functions: 0 18 0.0 %

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

Generated by: LCOV version 1.14