LCOV - code coverage report
Current view: top level - fs/proc - fd.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 171 188 91.0 %
Date: 2022-04-01 14:17:54 Functions: 14 15 93.3 %
Branches: 43 78 55.1 %

           Branch data     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/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                 :        660 : static int seq_show(struct seq_file *m, void *v)
      21                 :            : {
      22                 :        660 :         struct files_struct *files = NULL;
      23                 :        660 :         int f_flags = 0, ret = -ENOENT;
      24                 :        660 :         struct file *file = NULL;
      25                 :        660 :         struct task_struct *task;
      26                 :            : 
      27                 :        660 :         task = get_proc_task(m->private);
      28         [ +  - ]:        660 :         if (!task)
      29                 :            :                 return -ENOENT;
      30                 :            : 
      31                 :        660 :         files = get_files_struct(task);
      32                 :        660 :         put_task_struct(task);
      33                 :            : 
      34         [ +  - ]:        660 :         if (files) {
      35                 :        660 :                 unsigned int fd = proc_fd(m->private);
      36                 :            : 
      37                 :        660 :                 spin_lock(&files->file_lock);
      38         [ +  - ]:        660 :                 file = fcheck_files(files, fd);
      39         [ +  - ]:        660 :                 if (file) {
      40                 :        660 :                         struct fdtable *fdt = files_fdtable(files);
      41                 :            : 
      42                 :        660 :                         f_flags = file->f_flags;
      43         [ +  - ]:        660 :                         if (close_on_exec(fd, fdt))
      44                 :        660 :                                 f_flags |= O_CLOEXEC;
      45                 :            : 
      46                 :        660 :                         get_file(file);
      47                 :        660 :                         ret = 0;
      48                 :            :                 }
      49                 :        660 :                 spin_unlock(&files->file_lock);
      50                 :        660 :                 put_files_struct(files);
      51                 :            :         }
      52                 :            : 
      53         [ +  - ]:        660 :         if (ret)
      54                 :            :                 return ret;
      55                 :            : 
      56                 :        660 :         seq_printf(m, "pos:\t%lli\nflags:\t0%o\nmnt_id:\t%i\n",
      57                 :        660 :                    (long long)file->f_pos, f_flags,
      58                 :        660 :                    real_mount(file->f_path.mnt)->mnt_id);
      59                 :            : 
      60                 :        660 :         show_fd_locks(m, file, files);
      61         [ -  + ]:        660 :         if (seq_has_overflowed(m))
      62                 :          0 :                 goto out;
      63                 :            : 
      64         [ +  - ]:        660 :         if (file->f_op->show_fdinfo)
      65                 :          0 :                 file->f_op->show_fdinfo(m, file);
      66                 :            : 
      67                 :        660 : out:
      68                 :        660 :         fput(file);
      69                 :        660 :         return 0;
      70                 :            : }
      71                 :            : 
      72                 :        660 : static int seq_fdinfo_open(struct inode *inode, struct file *file)
      73                 :            : {
      74                 :        660 :         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                 :       3318 : static bool tid_fd_mode(struct task_struct *task, unsigned fd, fmode_t *mode)
      85                 :            : {
      86                 :       3318 :         struct files_struct *files = get_files_struct(task);
      87                 :       3318 :         struct file *file;
      88                 :            : 
      89         [ +  - ]:       3318 :         if (!files)
      90                 :            :                 return false;
      91                 :            : 
      92                 :       3318 :         rcu_read_lock();
      93         [ +  - ]:       3318 :         file = fcheck_files(files, fd);
      94         [ +  - ]:       3318 :         if (file)
      95                 :       3318 :                 *mode = file->f_mode;
      96                 :       3318 :         rcu_read_unlock();
      97                 :       3318 :         put_files_struct(files);
      98                 :       3318 :         return !!file;
      99                 :            : }
     100                 :            : 
     101                 :      17367 : static void tid_fd_update_inode(struct task_struct *task, struct inode *inode,
     102                 :            :                                 fmode_t f_mode)
     103                 :            : {
     104                 :      17367 :         task_dump_owner(task, 0, &inode->i_uid, &inode->i_gid);
     105                 :            : 
     106         [ +  + ]:      17367 :         if (S_ISLNK(inode->i_mode)) {
     107                 :      16707 :                 unsigned i_mode = S_IFLNK;
     108         [ +  + ]:      16707 :                 if (f_mode & FMODE_READ)
     109                 :      13103 :                         i_mode |= S_IRUSR | S_IXUSR;
     110         [ +  + ]:      16707 :                 if (f_mode & FMODE_WRITE)
     111                 :      10771 :                         i_mode |= S_IWUSR | S_IXUSR;
     112                 :      16707 :                 inode->i_mode = i_mode;
     113                 :            :         }
     114                 :      17367 :         security_task_to_inode(task, inode);
     115                 :      17367 : }
     116                 :            : 
     117                 :       2969 : static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags)
     118                 :            : {
     119                 :       2969 :         struct task_struct *task;
     120                 :       2969 :         struct inode *inode;
     121                 :       2969 :         unsigned int fd;
     122                 :            : 
     123         [ +  - ]:       2969 :         if (flags & LOOKUP_RCU)
     124                 :            :                 return -ECHILD;
     125                 :            : 
     126                 :       2969 :         inode = d_inode(dentry);
     127                 :       2969 :         task = get_proc_task(inode);
     128         [ +  - ]:       2969 :         fd = proc_fd(inode);
     129                 :            : 
     130         [ +  - ]:       2969 :         if (task) {
     131                 :       2969 :                 fmode_t f_mode;
     132         [ +  - ]:       2969 :                 if (tid_fd_mode(task, fd, &f_mode)) {
     133                 :       2969 :                         tid_fd_update_inode(task, inode, f_mode);
     134                 :       2969 :                         put_task_struct(task);
     135                 :       2969 :                         return 1;
     136                 :            :                 }
     137                 :          0 :                 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                 :       2658 : static int proc_fd_link(struct dentry *dentry, struct path *path)
     148                 :            : {
     149                 :       2658 :         struct files_struct *files = NULL;
     150                 :       2658 :         struct task_struct *task;
     151                 :       2658 :         int ret = -ENOENT;
     152                 :            : 
     153                 :       2658 :         task = get_proc_task(d_inode(dentry));
     154         [ +  - ]:       2658 :         if (task) {
     155                 :       2658 :                 files = get_files_struct(task);
     156                 :       2658 :                 put_task_struct(task);
     157                 :            :         }
     158                 :            : 
     159         [ +  - ]:       2658 :         if (files) {
     160                 :       2658 :                 unsigned int fd = proc_fd(d_inode(dentry));
     161                 :       2658 :                 struct file *fd_file;
     162                 :            : 
     163                 :       2658 :                 spin_lock(&files->file_lock);
     164         [ +  - ]:       2658 :                 fd_file = fcheck_files(files, fd);
     165         [ +  - ]:       2658 :                 if (fd_file) {
     166                 :       2658 :                         *path = fd_file->f_path;
     167                 :       2658 :                         path_get(&fd_file->f_path);
     168                 :       2658 :                         ret = 0;
     169                 :            :                 }
     170                 :       2658 :                 spin_unlock(&files->file_lock);
     171                 :       2658 :                 put_files_struct(files);
     172                 :            :         }
     173                 :            : 
     174                 :       2658 :         return ret;
     175                 :            : }
     176                 :            : 
     177                 :            : struct fd_data {
     178                 :            :         fmode_t mode;
     179                 :            :         unsigned fd;
     180                 :            : };
     181                 :            : 
     182                 :      14332 : static struct dentry *proc_fd_instantiate(struct dentry *dentry,
     183                 :            :         struct task_struct *task, const void *ptr)
     184                 :            : {
     185                 :      14332 :         const struct fd_data *data = ptr;
     186                 :      14332 :         struct proc_inode *ei;
     187                 :      14332 :         struct inode *inode;
     188                 :            : 
     189                 :      14332 :         inode = proc_pid_make_inode(dentry->d_sb, task, S_IFLNK);
     190         [ +  - ]:      14332 :         if (!inode)
     191                 :            :                 return ERR_PTR(-ENOENT);
     192                 :            : 
     193                 :      14332 :         ei = PROC_I(inode);
     194                 :      14332 :         ei->fd = data->fd;
     195                 :            : 
     196                 :      14332 :         inode->i_op = &proc_pid_link_inode_operations;
     197                 :      14332 :         inode->i_size = 64;
     198                 :            : 
     199                 :      14332 :         ei->op.proc_get_link = proc_fd_link;
     200                 :      14332 :         tid_fd_update_inode(task, inode, data->mode);
     201                 :            : 
     202                 :      14332 :         d_set_d_op(dentry, &tid_fd_dentry_operations);
     203                 :      14332 :         return d_splice_alias(inode, dentry);
     204                 :            : }
     205                 :            : 
     206                 :        349 : static struct dentry *proc_lookupfd_common(struct inode *dir,
     207                 :            :                                            struct dentry *dentry,
     208                 :            :                                            instantiate_t instantiate)
     209                 :            : {
     210                 :        349 :         struct task_struct *task = get_proc_task(dir);
     211                 :        349 :         struct fd_data data = {.fd = name_to_int(&dentry->d_name)};
     212         [ -  + ]:        349 :         struct dentry *result = ERR_PTR(-ENOENT);
     213                 :            : 
     214         [ -  + ]:        349 :         if (!task)
     215                 :          0 :                 goto out_no_task;
     216         [ -  + ]:        349 :         if (data.fd == ~0U)
     217                 :          0 :                 goto out;
     218         [ -  + ]:        349 :         if (!tid_fd_mode(task, data.fd, &data.mode))
     219                 :          0 :                 goto out;
     220                 :            : 
     221                 :        349 :         result = instantiate(dentry, task, &data);
     222                 :        349 : out:
     223                 :        349 :         put_task_struct(task);
     224                 :        349 : out_no_task:
     225                 :        349 :         return result;
     226                 :            : }
     227                 :            : 
     228                 :       1496 : static int proc_readfd_common(struct file *file, struct dir_context *ctx,
     229                 :            :                               instantiate_t instantiate)
     230                 :            : {
     231                 :       1496 :         struct task_struct *p = get_proc_task(file_inode(file));
     232                 :       1496 :         struct files_struct *files;
     233                 :       1496 :         unsigned int fd;
     234                 :            : 
     235         [ +  - ]:       1496 :         if (!p)
     236                 :            :                 return -ENOENT;
     237                 :            : 
     238         [ -  + ]:       1496 :         if (!dir_emit_dots(file, ctx))
     239                 :          0 :                 goto out;
     240                 :       1496 :         files = get_files_struct(p);
     241         [ -  + ]:       1496 :         if (!files)
     242                 :          0 :                 goto out;
     243                 :            : 
     244                 :       1496 :         rcu_read_lock();
     245         [ +  + ]:      49368 :         for (fd = ctx->pos - 2;
     246         [ +  + ]:      49368 :              fd < files_fdtable(files)->max_fds;
     247                 :      47872 :              fd++, ctx->pos++) {
     248                 :      47872 :                 struct file *f;
     249                 :      47872 :                 struct fd_data data;
     250                 :      47872 :                 char name[10 + 1];
     251                 :      47872 :                 unsigned int len;
     252                 :            : 
     253         [ +  - ]:      47872 :                 f = fcheck_files(files, fd);
     254         [ +  + ]:      47872 :                 if (!f)
     255                 :      32426 :                         continue;
     256                 :      15446 :                 data.mode = f->f_mode;
     257                 :      15446 :                 rcu_read_unlock();
     258                 :      15446 :                 data.fd = fd;
     259                 :            : 
     260                 :      15446 :                 len = snprintf(name, sizeof(name), "%u", fd);
     261         [ -  + ]:      15446 :                 if (!proc_fill_cache(file, ctx,
     262                 :            :                                      name, len, instantiate, p,
     263                 :            :                                      &data))
     264                 :          0 :                         goto out_fd_loop;
     265                 :      15446 :                 cond_resched();
     266                 :      15446 :                 rcu_read_lock();
     267                 :            :         }
     268                 :       1496 :         rcu_read_unlock();
     269                 :       1496 : out_fd_loop:
     270                 :       1496 :         put_files_struct(files);
     271                 :       1496 : out:
     272                 :       1496 :         put_task_struct(p);
     273                 :       1496 :         return 0;
     274                 :            : }
     275                 :            : 
     276                 :       1496 : static int proc_readfd(struct file *file, struct dir_context *ctx)
     277                 :            : {
     278                 :       1496 :         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                 :        283 : static struct dentry *proc_lookupfd(struct inode *dir, struct dentry *dentry,
     288                 :            :                                     unsigned int flags)
     289                 :            : {
     290                 :        283 :         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                 :       3406 : int proc_fd_permission(struct inode *inode, int mask)
     298                 :            : {
     299                 :       3406 :         struct task_struct *p;
     300                 :       3406 :         int rv;
     301                 :            : 
     302                 :       3406 :         rv = generic_permission(inode, mask);
     303         [ -  + ]:       3406 :         if (rv == 0)
     304                 :            :                 return rv;
     305                 :            : 
     306                 :          0 :         rcu_read_lock();
     307                 :          0 :         p = pid_task(proc_pid(inode), PIDTYPE_PID);
     308   [ #  #  #  # ]:          0 :         if (p && same_thread_group(p, current))
     309                 :          0 :                 rv = 0;
     310                 :          0 :         rcu_read_unlock();
     311                 :            : 
     312                 :          0 :         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                 :         66 : static struct dentry *proc_fdinfo_instantiate(struct dentry *dentry,
     322                 :            :         struct task_struct *task, const void *ptr)
     323                 :            : {
     324                 :         66 :         const struct fd_data *data = ptr;
     325                 :         66 :         struct proc_inode *ei;
     326                 :         66 :         struct inode *inode;
     327                 :            : 
     328                 :         66 :         inode = proc_pid_make_inode(dentry->d_sb, task, S_IFREG | S_IRUSR);
     329         [ +  - ]:         66 :         if (!inode)
     330                 :            :                 return ERR_PTR(-ENOENT);
     331                 :            : 
     332                 :         66 :         ei = PROC_I(inode);
     333                 :         66 :         ei->fd = data->fd;
     334                 :            : 
     335                 :         66 :         inode->i_fop = &proc_fdinfo_file_operations;
     336                 :         66 :         tid_fd_update_inode(task, inode, 0);
     337                 :            : 
     338                 :         66 :         d_set_d_op(dentry, &tid_fd_dentry_operations);
     339                 :         66 :         return d_splice_alias(inode, dentry);
     340                 :            : }
     341                 :            : 
     342                 :            : static struct dentry *
     343                 :         66 : proc_lookupfdinfo(struct inode *dir, struct dentry *dentry, unsigned int flags)
     344                 :            : {
     345                 :         66 :         return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate);
     346                 :            : }
     347                 :            : 
     348                 :          0 : static int proc_readfdinfo(struct file *file, struct dir_context *ctx)
     349                 :            : {
     350                 :          0 :         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                 :            : };

Generated by: LCOV version 1.14