root/fs/proc/fd.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. seq_show
  2. seq_fdinfo_open
  3. tid_fd_mode
  4. tid_fd_update_inode
  5. tid_fd_revalidate
  6. proc_fd_link
  7. proc_fd_instantiate
  8. proc_lookupfd_common
  9. proc_readfd_common
  10. proc_readfd
  11. proc_lookupfd
  12. proc_fd_permission
  13. proc_fdinfo_instantiate
  14. proc_lookupfdinfo
  15. proc_readfdinfo

   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/security.h>
  10 #include <linux/file.h>
  11 #include <linux/seq_file.h>
  12 #include <linux/fs.h>
  13 
  14 #include <linux/proc_fs.h>
  15 
  16 #include "../mount.h"
  17 #include "internal.h"
  18 #include "fd.h"
  19 
  20 static int seq_show(struct seq_file *m, void *v)
  21 {
  22         struct files_struct *files = NULL;
  23         int f_flags = 0, ret = -ENOENT;
  24         struct file *file = NULL;
  25         struct task_struct *task;
  26 
  27         task = get_proc_task(m->private);
  28         if (!task)
  29                 return -ENOENT;
  30 
  31         files = get_files_struct(task);
  32         put_task_struct(task);
  33 
  34         if (files) {
  35                 unsigned int fd = proc_fd(m->private);
  36 
  37                 spin_lock(&files->file_lock);
  38                 file = fcheck_files(files, fd);
  39                 if (file) {
  40                         struct fdtable *fdt = files_fdtable(files);
  41 
  42                         f_flags = file->f_flags;
  43                         if (close_on_exec(fd, fdt))
  44                                 f_flags |= O_CLOEXEC;
  45 
  46                         get_file(file);
  47                         ret = 0;
  48                 }
  49                 spin_unlock(&files->file_lock);
  50                 put_files_struct(files);
  51         }
  52 
  53         if (ret)
  54                 return ret;
  55 
  56         seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n",
  57                    (long long)file->f_pos, f_flags,
  58                    real_mount(file->f_path.mnt)->mnt_id);
  59 
  60         show_fd_locks(m, file, files);
  61         if (seq_has_overflowed(m))
  62                 goto out;
  63 
  64         if (file->f_op->show_fdinfo)
  65                 file->f_op->show_fdinfo(m, file);
  66 
  67 out:
  68         fput(file);
  69         return 0;
  70 }
  71 
  72 static int seq_fdinfo_open(struct inode *inode, struct file *file)
  73 {
  74         return single_open(file, seq_show, inode);
  75 }
  76 
  77 static const struct file_operations proc_fdinfo_file_operations = {
  78         .open           = seq_fdinfo_open,
  79         .read           = seq_read,
  80         .llseek         = seq_lseek,
  81         .release        = single_release,
  82 };
  83 
  84 static bool tid_fd_mode(struct task_struct *task, unsigned fd, fmode_t *mode)
  85 {
  86         struct files_struct *files = get_files_struct(task);
  87         struct file *file;
  88 
  89         if (!files)
  90                 return false;
  91 
  92         rcu_read_lock();
  93         file = fcheck_files(files, fd);
  94         if (file)
  95                 *mode = file->f_mode;
  96         rcu_read_unlock();
  97         put_files_struct(files);
  98         return !!file;
  99 }
 100 
 101 static void tid_fd_update_inode(struct task_struct *task, struct inode *inode,
 102                                 fmode_t f_mode)
 103 {
 104         task_dump_owner(task, 0, &inode->i_uid, &inode->i_gid);
 105 
 106         if (S_ISLNK(inode->i_mode)) {
 107                 unsigned i_mode = S_IFLNK;
 108                 if (f_mode & FMODE_READ)
 109                         i_mode |= S_IRUSR | S_IXUSR;
 110                 if (f_mode & FMODE_WRITE)
 111                         i_mode |= S_IWUSR | S_IXUSR;
 112                 inode->i_mode = i_mode;
 113         }
 114         security_task_to_inode(task, inode);
 115 }
 116 
 117 static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags)
 118 {
 119         struct task_struct *task;
 120         struct inode *inode;
 121         unsigned int fd;
 122 
 123         if (flags & LOOKUP_RCU)
 124                 return -ECHILD;
 125 
 126         inode = d_inode(dentry);
 127         task = get_proc_task(inode);
 128         fd = proc_fd(inode);
 129 
 130         if (task) {
 131                 fmode_t f_mode;
 132                 if (tid_fd_mode(task, fd, &f_mode)) {
 133                         tid_fd_update_inode(task, inode, f_mode);
 134                         put_task_struct(task);
 135                         return 1;
 136                 }
 137                 put_task_struct(task);
 138         }
 139         return 0;
 140 }
 141 
 142 static const struct dentry_operations tid_fd_dentry_operations = {
 143         .d_revalidate   = tid_fd_revalidate,
 144         .d_delete       = pid_delete_dentry,
 145 };
 146 
 147 static int proc_fd_link(struct dentry *dentry, struct path *path)
 148 {
 149         struct files_struct *files = NULL;
 150         struct task_struct *task;
 151         int ret = -ENOENT;
 152 
 153         task = get_proc_task(d_inode(dentry));
 154         if (task) {
 155                 files = get_files_struct(task);
 156                 put_task_struct(task);
 157         }
 158 
 159         if (files) {
 160                 unsigned int fd = proc_fd(d_inode(dentry));
 161                 struct file *fd_file;
 162 
 163                 spin_lock(&files->file_lock);
 164                 fd_file = fcheck_files(files, fd);
 165                 if (fd_file) {
 166                         *path = fd_file->f_path;
 167                         path_get(&fd_file->f_path);
 168                         ret = 0;
 169                 }
 170                 spin_unlock(&files->file_lock);
 171                 put_files_struct(files);
 172         }
 173 
 174         return ret;
 175 }
 176 
 177 struct fd_data {
 178         fmode_t mode;
 179         unsigned fd;
 180 };
 181 
 182 static struct dentry *proc_fd_instantiate(struct dentry *dentry,
 183         struct task_struct *task, const void *ptr)
 184 {
 185         const struct fd_data *data = ptr;
 186         struct proc_inode *ei;
 187         struct inode *inode;
 188 
 189         inode = proc_pid_make_inode(dentry->d_sb, task, S_IFLNK);
 190         if (!inode)
 191                 return ERR_PTR(-ENOENT);
 192 
 193         ei = PROC_I(inode);
 194         ei->fd = data->fd;
 195 
 196         inode->i_op = &proc_pid_link_inode_operations;
 197         inode->i_size = 64;
 198 
 199         ei->op.proc_get_link = proc_fd_link;
 200         tid_fd_update_inode(task, inode, data->mode);
 201 
 202         d_set_d_op(dentry, &tid_fd_dentry_operations);
 203         return d_splice_alias(inode, dentry);
 204 }
 205 
 206 static struct dentry *proc_lookupfd_common(struct inode *dir,
 207                                            struct dentry *dentry,
 208                                            instantiate_t instantiate)
 209 {
 210         struct task_struct *task = get_proc_task(dir);
 211         struct fd_data data = {.fd = name_to_int(&dentry->d_name)};
 212         struct dentry *result = ERR_PTR(-ENOENT);
 213 
 214         if (!task)
 215                 goto out_no_task;
 216         if (data.fd == ~0U)
 217                 goto out;
 218         if (!tid_fd_mode(task, data.fd, &data.mode))
 219                 goto out;
 220 
 221         result = instantiate(dentry, task, &data);
 222 out:
 223         put_task_struct(task);
 224 out_no_task:
 225         return result;
 226 }
 227 
 228 static int proc_readfd_common(struct file *file, struct dir_context *ctx,
 229                               instantiate_t instantiate)
 230 {
 231         struct task_struct *p = get_proc_task(file_inode(file));
 232         struct files_struct *files;
 233         unsigned int fd;
 234 
 235         if (!p)
 236                 return -ENOENT;
 237 
 238         if (!dir_emit_dots(file, ctx))
 239                 goto out;
 240         files = get_files_struct(p);
 241         if (!files)
 242                 goto out;
 243 
 244         rcu_read_lock();
 245         for (fd = ctx->pos - 2;
 246              fd < files_fdtable(files)->max_fds;
 247              fd++, ctx->pos++) {
 248                 struct file *f;
 249                 struct fd_data data;
 250                 char name[10 + 1];
 251                 unsigned int len;
 252 
 253                 f = fcheck_files(files, fd);
 254                 if (!f)
 255                         continue;
 256                 data.mode = f->f_mode;
 257                 rcu_read_unlock();
 258                 data.fd = fd;
 259 
 260                 len = snprintf(name, sizeof(name), "%u", fd);
 261                 if (!proc_fill_cache(file, ctx,
 262                                      name, len, instantiate, p,
 263                                      &data))
 264                         goto out_fd_loop;
 265                 cond_resched();
 266                 rcu_read_lock();
 267         }
 268         rcu_read_unlock();
 269 out_fd_loop:
 270         put_files_struct(files);
 271 out:
 272         put_task_struct(p);
 273         return 0;
 274 }
 275 
 276 static int proc_readfd(struct file *file, struct dir_context *ctx)
 277 {
 278         return proc_readfd_common(file, ctx, proc_fd_instantiate);
 279 }
 280 
 281 const struct file_operations proc_fd_operations = {
 282         .read           = generic_read_dir,
 283         .iterate_shared = proc_readfd,
 284         .llseek         = generic_file_llseek,
 285 };
 286 
 287 static struct dentry *proc_lookupfd(struct inode *dir, struct dentry *dentry,
 288                                     unsigned int flags)
 289 {
 290         return proc_lookupfd_common(dir, dentry, proc_fd_instantiate);
 291 }
 292 
 293 /*
 294  * /proc/pid/fd needs a special permission handler so that a process can still
 295  * access /proc/self/fd after it has executed a setuid().
 296  */
 297 int proc_fd_permission(struct inode *inode, int mask)
 298 {
 299         struct task_struct *p;
 300         int rv;
 301 
 302         rv = generic_permission(inode, mask);
 303         if (rv == 0)
 304                 return rv;
 305 
 306         rcu_read_lock();
 307         p = pid_task(proc_pid(inode), PIDTYPE_PID);
 308         if (p && same_thread_group(p, current))
 309                 rv = 0;
 310         rcu_read_unlock();
 311 
 312         return rv;
 313 }
 314 
 315 const struct inode_operations proc_fd_inode_operations = {
 316         .lookup         = proc_lookupfd,
 317         .permission     = proc_fd_permission,
 318         .setattr        = proc_setattr,
 319 };
 320 
 321 static struct dentry *proc_fdinfo_instantiate(struct dentry *dentry,
 322         struct task_struct *task, const void *ptr)
 323 {
 324         const struct fd_data *data = ptr;
 325         struct proc_inode *ei;
 326         struct inode *inode;
 327 
 328         inode = proc_pid_make_inode(dentry->d_sb, task, S_IFREG | S_IRUSR);
 329         if (!inode)
 330                 return ERR_PTR(-ENOENT);
 331 
 332         ei = PROC_I(inode);
 333         ei->fd = data->fd;
 334 
 335         inode->i_fop = &proc_fdinfo_file_operations;
 336         tid_fd_update_inode(task, inode, 0);
 337 
 338         d_set_d_op(dentry, &tid_fd_dentry_operations);
 339         return d_splice_alias(inode, dentry);
 340 }
 341 
 342 static struct dentry *
 343 proc_lookupfdinfo(struct inode *dir, struct dentry *dentry, unsigned int flags)
 344 {
 345         return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate);
 346 }
 347 
 348 static int proc_readfdinfo(struct file *file, struct dir_context *ctx)
 349 {
 350         return proc_readfd_common(file, ctx,
 351                                   proc_fdinfo_instantiate);
 352 }
 353 
 354 const struct inode_operations proc_fdinfo_inode_operations = {
 355         .lookup         = proc_lookupfdinfo,
 356         .setattr        = proc_setattr,
 357 };
 358 
 359 const struct file_operations proc_fdinfo_operations = {
 360         .read           = generic_read_dir,
 361         .iterate_shared = proc_readfdinfo,
 362         .llseek         = generic_file_llseek,
 363 };

/* [<][>][^][v][top][bottom][index][help] */