LCOV - code coverage report
Current view: top level - fs/proc - fd.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 93 112 83.0 %
Date: 2014-02-18 Functions: 12 13 92.3 %
Branches: 38 61 62.3 %

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

Generated by: LCOV version 1.9