linux/fs/proc/fd.c
<<
>>
Prefs
   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
  20static 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
  67out:
  68        fput(file);
  69        return 0;
  70}
  71
  72static int seq_fdinfo_open(struct inode *inode, struct file *file)
  73{
  74        return single_open(file, seq_show, inode);
  75}
  76
  77static 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
  84static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags)
  85{
  86        struct files_struct *files;
  87        struct task_struct *task;
  88        struct inode *inode;
  89        unsigned int fd;
  90
  91        if (flags & LOOKUP_RCU)
  92                return -ECHILD;
  93
  94        inode = d_inode(dentry);
  95        task = get_proc_task(inode);
  96        fd = proc_fd(inode);
  97
  98        if (task) {
  99                files = get_files_struct(task);
 100                if (files) {
 101                        struct file *file;
 102
 103                        rcu_read_lock();
 104                        file = fcheck_files(files, fd);
 105                        if (file) {
 106                                unsigned f_mode = file->f_mode;
 107
 108                                rcu_read_unlock();
 109                                put_files_struct(files);
 110
 111                                task_dump_owner(task, 0, &inode->i_uid, &inode->i_gid);
 112
 113                                if (S_ISLNK(inode->i_mode)) {
 114                                        unsigned i_mode = S_IFLNK;
 115                                        if (f_mode & FMODE_READ)
 116                                                i_mode |= S_IRUSR | S_IXUSR;
 117                                        if (f_mode & FMODE_WRITE)
 118                                                i_mode |= S_IWUSR | S_IXUSR;
 119                                        inode->i_mode = i_mode;
 120                                }
 121
 122                                security_task_to_inode(task, inode);
 123                                put_task_struct(task);
 124                                return 1;
 125                        }
 126                        rcu_read_unlock();
 127                        put_files_struct(files);
 128                }
 129                put_task_struct(task);
 130        }
 131        return 0;
 132}
 133
 134static const struct dentry_operations tid_fd_dentry_operations = {
 135        .d_revalidate   = tid_fd_revalidate,
 136        .d_delete       = pid_delete_dentry,
 137};
 138
 139static int proc_fd_link(struct dentry *dentry, struct path *path)
 140{
 141        struct files_struct *files = NULL;
 142        struct task_struct *task;
 143        int ret = -ENOENT;
 144
 145        task = get_proc_task(d_inode(dentry));
 146        if (task) {
 147                files = get_files_struct(task);
 148                put_task_struct(task);
 149        }
 150
 151        if (files) {
 152                unsigned int fd = proc_fd(d_inode(dentry));
 153                struct file *fd_file;
 154
 155                spin_lock(&files->file_lock);
 156                fd_file = fcheck_files(files, fd);
 157                if (fd_file) {
 158                        *path = fd_file->f_path;
 159                        path_get(&fd_file->f_path);
 160                        ret = 0;
 161                }
 162                spin_unlock(&files->file_lock);
 163                put_files_struct(files);
 164        }
 165
 166        return ret;
 167}
 168
 169static int
 170proc_fd_instantiate(struct inode *dir, struct dentry *dentry,
 171                    struct task_struct *task, const void *ptr)
 172{
 173        unsigned fd = (unsigned long)ptr;
 174        struct proc_inode *ei;
 175        struct inode *inode;
 176
 177        inode = proc_pid_make_inode(dir->i_sb, task, S_IFLNK);
 178        if (!inode)
 179                goto out;
 180
 181        ei = PROC_I(inode);
 182        ei->fd = fd;
 183
 184        inode->i_op = &proc_pid_link_inode_operations;
 185        inode->i_size = 64;
 186
 187        ei->op.proc_get_link = proc_fd_link;
 188
 189        d_set_d_op(dentry, &tid_fd_dentry_operations);
 190        d_add(dentry, inode);
 191
 192        /* Close the race of the process dying before we return the dentry */
 193        if (tid_fd_revalidate(dentry, 0))
 194                return 0;
 195 out:
 196        return -ENOENT;
 197}
 198
 199static struct dentry *proc_lookupfd_common(struct inode *dir,
 200                                           struct dentry *dentry,
 201                                           instantiate_t instantiate)
 202{
 203        struct task_struct *task = get_proc_task(dir);
 204        int result = -ENOENT;
 205        unsigned fd = name_to_int(&dentry->d_name);
 206
 207        if (!task)
 208                goto out_no_task;
 209        if (fd == ~0U)
 210                goto out;
 211
 212        result = instantiate(dir, dentry, task, (void *)(unsigned long)fd);
 213out:
 214        put_task_struct(task);
 215out_no_task:
 216        return ERR_PTR(result);
 217}
 218
 219static int proc_readfd_common(struct file *file, struct dir_context *ctx,
 220                              instantiate_t instantiate)
 221{
 222        struct task_struct *p = get_proc_task(file_inode(file));
 223        struct files_struct *files;
 224        unsigned int fd;
 225
 226        if (!p)
 227                return -ENOENT;
 228
 229        if (!dir_emit_dots(file, ctx))
 230                goto out;
 231        files = get_files_struct(p);
 232        if (!files)
 233                goto out;
 234
 235        rcu_read_lock();
 236        for (fd = ctx->pos - 2;
 237             fd < files_fdtable(files)->max_fds;
 238             fd++, ctx->pos++) {
 239                char name[PROC_NUMBUF];
 240                int len;
 241
 242                if (!fcheck_files(files, fd))
 243                        continue;
 244                rcu_read_unlock();
 245
 246                len = snprintf(name, sizeof(name), "%u", fd);
 247                if (!proc_fill_cache(file, ctx,
 248                                     name, len, instantiate, p,
 249                                     (void *)(unsigned long)fd))
 250                        goto out_fd_loop;
 251                cond_resched();
 252                rcu_read_lock();
 253        }
 254        rcu_read_unlock();
 255out_fd_loop:
 256        put_files_struct(files);
 257out:
 258        put_task_struct(p);
 259        return 0;
 260}
 261
 262static int proc_readfd(struct file *file, struct dir_context *ctx)
 263{
 264        return proc_readfd_common(file, ctx, proc_fd_instantiate);
 265}
 266
 267const struct file_operations proc_fd_operations = {
 268        .read           = generic_read_dir,
 269        .iterate_shared = proc_readfd,
 270        .llseek         = generic_file_llseek,
 271};
 272
 273static struct dentry *proc_lookupfd(struct inode *dir, struct dentry *dentry,
 274                                    unsigned int flags)
 275{
 276        return proc_lookupfd_common(dir, dentry, proc_fd_instantiate);
 277}
 278
 279/*
 280 * /proc/pid/fd needs a special permission handler so that a process can still
 281 * access /proc/self/fd after it has executed a setuid().
 282 */
 283int proc_fd_permission(struct inode *inode, int mask)
 284{
 285        struct task_struct *p;
 286        int rv;
 287
 288        rv = generic_permission(inode, mask);
 289        if (rv == 0)
 290                return rv;
 291
 292        rcu_read_lock();
 293        p = pid_task(proc_pid(inode), PIDTYPE_PID);
 294        if (p && same_thread_group(p, current))
 295                rv = 0;
 296        rcu_read_unlock();
 297
 298        return rv;
 299}
 300
 301const struct inode_operations proc_fd_inode_operations = {
 302        .lookup         = proc_lookupfd,
 303        .permission     = proc_fd_permission,
 304        .setattr        = proc_setattr,
 305};
 306
 307static int
 308proc_fdinfo_instantiate(struct inode *dir, struct dentry *dentry,
 309                        struct task_struct *task, const void *ptr)
 310{
 311        unsigned fd = (unsigned long)ptr;
 312        struct proc_inode *ei;
 313        struct inode *inode;
 314
 315        inode = proc_pid_make_inode(dir->i_sb, task, S_IFREG | S_IRUSR);
 316        if (!inode)
 317                goto out;
 318
 319        ei = PROC_I(inode);
 320        ei->fd = fd;
 321
 322        inode->i_fop = &proc_fdinfo_file_operations;
 323
 324        d_set_d_op(dentry, &tid_fd_dentry_operations);
 325        d_add(dentry, inode);
 326
 327        /* Close the race of the process dying before we return the dentry */
 328        if (tid_fd_revalidate(dentry, 0))
 329                return 0;
 330 out:
 331        return -ENOENT;
 332}
 333
 334static struct dentry *
 335proc_lookupfdinfo(struct inode *dir, struct dentry *dentry, unsigned int flags)
 336{
 337        return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate);
 338}
 339
 340static int proc_readfdinfo(struct file *file, struct dir_context *ctx)
 341{
 342        return proc_readfd_common(file, ctx,
 343                                  proc_fdinfo_instantiate);
 344}
 345
 346const struct inode_operations proc_fdinfo_inode_operations = {
 347        .lookup         = proc_lookupfdinfo,
 348        .setattr        = proc_setattr,
 349};
 350
 351const struct file_operations proc_fdinfo_operations = {
 352        .read           = generic_read_dir,
 353        .iterate_shared = proc_readfdinfo,
 354        .llseek         = generic_file_llseek,
 355};
 356