LCOV - code coverage report
Current view: top level - fs/proc - generic.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 237 372 63.7 %
Date: 2022-04-01 13:59:58 Functions: 29 39 74.4 %
Branches: 84 178 47.2 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : /*
       3                 :            :  * proc/fs/generic.c --- generic routines for the proc-fs
       4                 :            :  *
       5                 :            :  * This file contains generic proc-fs routines for handling
       6                 :            :  * directories and files.
       7                 :            :  * 
       8                 :            :  * Copyright (C) 1991, 1992 Linus Torvalds.
       9                 :            :  * Copyright (C) 1997 Theodore Ts'o
      10                 :            :  */
      11                 :            : 
      12                 :            : #include <linux/cache.h>
      13                 :            : #include <linux/errno.h>
      14                 :            : #include <linux/time.h>
      15                 :            : #include <linux/proc_fs.h>
      16                 :            : #include <linux/stat.h>
      17                 :            : #include <linux/mm.h>
      18                 :            : #include <linux/module.h>
      19                 :            : #include <linux/namei.h>
      20                 :            : #include <linux/slab.h>
      21                 :            : #include <linux/printk.h>
      22                 :            : #include <linux/mount.h>
      23                 :            : #include <linux/init.h>
      24                 :            : #include <linux/idr.h>
      25                 :            : #include <linux/bitops.h>
      26                 :            : #include <linux/spinlock.h>
      27                 :            : #include <linux/completion.h>
      28                 :            : #include <linux/uaccess.h>
      29                 :            : #include <linux/seq_file.h>
      30                 :            : 
      31                 :            : #include "internal.h"
      32                 :            : 
      33                 :            : static DEFINE_RWLOCK(proc_subdir_lock);
      34                 :            : 
      35                 :            : struct kmem_cache *proc_dir_entry_cache __ro_after_init;
      36                 :            : 
      37                 :         78 : void pde_free(struct proc_dir_entry *pde)
      38                 :            : {
      39         [ -  + ]:         78 :         if (S_ISLNK(pde->mode))
      40                 :          0 :                 kfree(pde->data);
      41         [ -  + ]:         78 :         if (pde->name != pde->inline_name)
      42                 :          0 :                 kfree(pde->name);
      43                 :         78 :         kmem_cache_free(proc_dir_entry_cache, pde);
      44                 :         78 : }
      45                 :            : 
      46                 :     111602 : static int proc_match(const char *name, struct proc_dir_entry *de, unsigned int len)
      47                 :            : {
      48                 :     111602 :         if (len < de->namelen)
      49                 :            :                 return -1;
      50   [ +  +  +  + ]:      76959 :         if (len > de->namelen)
      51                 :            :                 return 1;
      52                 :            : 
      53                 :      36118 :         return memcmp(name, de->name, len);
      54                 :            : }
      55                 :            : 
      56                 :         78 : static struct proc_dir_entry *pde_subdir_first(struct proc_dir_entry *dir)
      57                 :            : {
      58   [ -  +  -  -  :         78 :         return rb_entry_safe(rb_first(&dir->subdir), struct proc_dir_entry,
             -  -  -  - ]
      59                 :            :                              subdir_node);
      60                 :            : }
      61                 :            : 
      62                 :          0 : static struct proc_dir_entry *pde_subdir_next(struct proc_dir_entry *dir)
      63                 :            : {
      64   [ #  #  #  # ]:          0 :         return rb_entry_safe(rb_next(&dir->subdir_node), struct proc_dir_entry,
      65                 :            :                              subdir_node);
      66                 :            : }
      67                 :            : 
      68                 :       8705 : static struct proc_dir_entry *pde_subdir_find(struct proc_dir_entry *dir,
      69                 :            :                                               const char *name,
      70                 :            :                                               unsigned int len)
      71                 :            : {
      72                 :       8705 :         struct rb_node *node = dir->subdir.rb_node;
      73                 :            : 
      74         [ +  + ]:      43669 :         while (node) {
      75                 :      39131 :                 struct proc_dir_entry *de = rb_entry(node,
      76                 :            :                                                      struct proc_dir_entry,
      77                 :            :                                                      subdir_node);
      78         [ +  + ]:      39131 :                 int result = proc_match(name, de, len);
      79                 :            : 
      80         [ +  + ]:      16552 :                 if (result < 0)
      81                 :      20811 :                         node = node->rb_left;
      82         [ +  + ]:      18320 :                 else if (result > 0)
      83                 :      14153 :                         node = node->rb_right;
      84                 :            :                 else
      85                 :       4167 :                         return de;
      86                 :            :         }
      87                 :            :         return NULL;
      88                 :            : }
      89                 :            : 
      90                 :      26664 : static bool pde_subdir_insert(struct proc_dir_entry *dir,
      91                 :            :                               struct proc_dir_entry *de)
      92                 :            : {
      93                 :      26664 :         struct rb_root *root = &dir->subdir;
      94                 :      26664 :         struct rb_node **new = &root->rb_node, *parent = NULL;
      95                 :            : 
      96                 :            :         /* Figure out where to put new node */
      97         [ +  + ]:      99135 :         while (*new) {
      98                 :      72471 :                 struct proc_dir_entry *this = rb_entry(*new,
      99                 :            :                                                        struct proc_dir_entry,
     100                 :            :                                                        subdir_node);
     101         [ +  + ]:      72471 :                 int result = proc_match(de->name, this, de->namelen);
     102                 :            : 
     103                 :      19566 :                 parent = *new;
     104         [ +  + ]:      19566 :                 if (result < 0)
     105                 :      26262 :                         new = &(*new)->rb_left;
     106         [ +  - ]:      46209 :                 else if (result > 0)
     107                 :      46209 :                         new = &(*new)->rb_right;
     108                 :            :                 else
     109                 :            :                         return false;
     110                 :            :         }
     111                 :            : 
     112                 :            :         /* Add new node and rebalance tree. */
     113                 :      26664 :         rb_link_node(&de->subdir_node, parent, new);
     114                 :      26664 :         rb_insert_color(&de->subdir_node, root);
     115                 :      26664 :         return true;
     116                 :            : }
     117                 :            : 
     118                 :          0 : static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
     119                 :            : {
     120                 :          0 :         struct inode *inode = d_inode(dentry);
     121                 :          0 :         struct proc_dir_entry *de = PDE(inode);
     122                 :          0 :         int error;
     123                 :            : 
     124                 :          0 :         error = setattr_prepare(dentry, iattr);
     125         [ #  # ]:          0 :         if (error)
     126                 :            :                 return error;
     127                 :            : 
     128                 :          0 :         setattr_copy(inode, iattr);
     129                 :          0 :         mark_inode_dirty(inode);
     130                 :            : 
     131                 :          0 :         proc_set_user(de, inode->i_uid, inode->i_gid);
     132                 :          0 :         de->mode = inode->i_mode;
     133                 :          0 :         return 0;
     134                 :            : }
     135                 :            : 
     136                 :        936 : static int proc_getattr(const struct path *path, struct kstat *stat,
     137                 :            :                         u32 request_mask, unsigned int query_flags)
     138                 :            : {
     139         [ +  - ]:        936 :         struct inode *inode = d_inode(path->dentry);
     140         [ +  - ]:        936 :         struct proc_dir_entry *de = PDE(inode);
     141         [ +  - ]:        936 :         if (de) {
     142         [ +  - ]:        936 :                 nlink_t nlink = READ_ONCE(de->nlink);
     143         [ +  - ]:        936 :                 if (nlink > 0) {
     144                 :        936 :                         set_nlink(inode, nlink);
     145                 :            :                 }
     146                 :            :         }
     147                 :            : 
     148                 :        936 :         generic_fillattr(inode, stat);
     149                 :        936 :         return 0;
     150                 :            : }
     151                 :            : 
     152                 :            : static const struct inode_operations proc_file_inode_operations = {
     153                 :            :         .setattr        = proc_notify_change,
     154                 :            : };
     155                 :            : 
     156                 :            : /*
     157                 :            :  * This function parses a name such as "tty/driver/serial", and
     158                 :            :  * returns the struct proc_dir_entry for "/proc/tty/driver", and
     159                 :            :  * returns "serial" in residual.
     160                 :            :  */
     161                 :      26742 : static int __xlate_proc_name(const char *name, struct proc_dir_entry **ret,
     162                 :            :                              const char **residual)
     163                 :            : {
     164                 :      26742 :         const char              *cp = name, *next;
     165                 :      26742 :         struct proc_dir_entry   *de;
     166                 :            : 
     167                 :      26742 :         de = *ret;
     168         [ +  + ]:      26742 :         if (!de)
     169                 :       6006 :                 de = &proc_root;
     170                 :            : 
     171                 :      30642 :         while (1) {
     172                 :      30642 :                 next = strchr(cp, '/');
     173         [ +  + ]:      28692 :                 if (!next)
     174                 :            :                         break;
     175                 :            : 
     176                 :       1950 :                 de = pde_subdir_find(de, cp, next - cp);
     177         [ -  + ]:       1950 :                 if (!de) {
     178                 :          0 :                         WARN(1, "name '%s'\n", name);
     179                 :          0 :                         return -ENOENT;
     180                 :            :                 }
     181                 :       1950 :                 cp = next + 1;
     182                 :            :         }
     183                 :      26742 :         *residual = cp;
     184                 :      26742 :         *ret = de;
     185                 :      26742 :         return 0;
     186                 :            : }
     187                 :            : 
     188                 :      26664 : static int xlate_proc_name(const char *name, struct proc_dir_entry **ret,
     189                 :            :                            const char **residual)
     190                 :            : {
     191                 :      26664 :         int rv;
     192                 :            : 
     193                 :      26664 :         read_lock(&proc_subdir_lock);
     194                 :      26664 :         rv = __xlate_proc_name(name, ret, residual);
     195                 :      26664 :         read_unlock(&proc_subdir_lock);
     196                 :      26664 :         return rv;
     197                 :            : }
     198                 :            : 
     199                 :            : static DEFINE_IDA(proc_inum_ida);
     200                 :            : 
     201                 :            : #define PROC_DYNAMIC_FIRST 0xF0000000U
     202                 :            : 
     203                 :            : /*
     204                 :            :  * Return an inode number between PROC_DYNAMIC_FIRST and
     205                 :            :  * 0xffffffff, or zero on failure.
     206                 :            :  */
     207                 :      27210 : int proc_alloc_inum(unsigned int *inum)
     208                 :            : {
     209                 :      27210 :         int i;
     210                 :            : 
     211                 :        546 :         i = ida_simple_get(&proc_inum_ida, 0, UINT_MAX - PROC_DYNAMIC_FIRST + 1,
     212                 :            :                            GFP_KERNEL);
     213   [ +  -  +  - ]:      27210 :         if (i < 0)
     214                 :            :                 return i;
     215                 :            : 
     216                 :      27210 :         *inum = PROC_DYNAMIC_FIRST + (unsigned int)i;
     217                 :        546 :         return 0;
     218                 :            : }
     219                 :            : 
     220                 :         78 : void proc_free_inum(unsigned int inum)
     221                 :            : {
     222                 :          0 :         ida_simple_remove(&proc_inum_ida, inum - PROC_DYNAMIC_FIRST);
     223                 :          0 : }
     224                 :            : 
     225                 :      36834 : static int proc_misc_d_revalidate(struct dentry *dentry, unsigned int flags)
     226                 :            : {
     227         [ +  + ]:      36834 :         if (flags & LOOKUP_RCU)
     228                 :            :                 return -ECHILD;
     229                 :            : 
     230         [ -  + ]:      18417 :         if (atomic_read(&PDE(d_inode(dentry))->in_use) < 0)
     231                 :          0 :                 return 0; /* revalidate */
     232                 :            :         return 1;
     233                 :            : }
     234                 :            : 
     235                 :       9337 : static int proc_misc_d_delete(const struct dentry *dentry)
     236                 :            : {
     237                 :       9337 :         return atomic_read(&PDE(d_inode(dentry))->in_use) < 0;
     238                 :            : }
     239                 :            : 
     240                 :            : static const struct dentry_operations proc_misc_dentry_ops = {
     241                 :            :         .d_revalidate   = proc_misc_d_revalidate,
     242                 :            :         .d_delete       = proc_misc_d_delete,
     243                 :            : };
     244                 :            : 
     245                 :            : /*
     246                 :            :  * Don't create negative dentries here, return -ENOENT by hand
     247                 :            :  * instead.
     248                 :            :  */
     249                 :       6677 : struct dentry *proc_lookup_de(struct inode *dir, struct dentry *dentry,
     250                 :            :                               struct proc_dir_entry *de)
     251                 :            : {
     252                 :       6677 :         struct inode *inode;
     253                 :            : 
     254                 :       6677 :         read_lock(&proc_subdir_lock);
     255                 :       6677 :         de = pde_subdir_find(de, dentry->d_name.name, dentry->d_name.len);
     256         [ +  + ]:       6677 :         if (de) {
     257                 :       2139 :                 pde_get(de);
     258                 :       2139 :                 read_unlock(&proc_subdir_lock);
     259                 :       2139 :                 inode = proc_get_inode(dir->i_sb, de);
     260         [ +  - ]:       2139 :                 if (!inode)
     261                 :            :                         return ERR_PTR(-ENOMEM);
     262                 :       2139 :                 d_set_d_op(dentry, de->proc_dops);
     263                 :       2139 :                 return d_splice_alias(inode, dentry);
     264                 :            :         }
     265                 :       4538 :         read_unlock(&proc_subdir_lock);
     266                 :       4538 :         return ERR_PTR(-ENOENT);
     267                 :            : }
     268                 :            : 
     269                 :       5942 : struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry,
     270                 :            :                 unsigned int flags)
     271                 :            : {
     272                 :       5942 :         return proc_lookup_de(dir, dentry, PDE(dir));
     273                 :            : }
     274                 :            : 
     275                 :            : /*
     276                 :            :  * This returns non-zero if at EOF, so that the /proc
     277                 :            :  * root directory can use this and check if it should
     278                 :            :  * continue with the <pid> entries..
     279                 :            :  *
     280                 :            :  * Note that the VFS-layer doesn't care about the return
     281                 :            :  * value of the readdir() call, as long as it's non-negative
     282                 :            :  * for success..
     283                 :            :  */
     284                 :          0 : int proc_readdir_de(struct file *file, struct dir_context *ctx,
     285                 :            :                     struct proc_dir_entry *de)
     286                 :            : {
     287                 :          0 :         int i;
     288                 :            : 
     289         [ #  # ]:          0 :         if (!dir_emit_dots(file, ctx))
     290                 :            :                 return 0;
     291                 :            : 
     292                 :          0 :         i = ctx->pos - 2;
     293                 :          0 :         read_lock(&proc_subdir_lock);
     294                 :          0 :         de = pde_subdir_first(de);
     295                 :          0 :         for (;;) {
     296         [ #  # ]:          0 :                 if (!de) {
     297                 :          0 :                         read_unlock(&proc_subdir_lock);
     298                 :          0 :                         return 0;
     299                 :            :                 }
     300         [ #  # ]:          0 :                 if (!i)
     301                 :            :                         break;
     302                 :          0 :                 de = pde_subdir_next(de);
     303                 :          0 :                 i--;
     304                 :            :         }
     305                 :            : 
     306                 :          0 :         do {
     307                 :          0 :                 struct proc_dir_entry *next;
     308                 :          0 :                 pde_get(de);
     309                 :          0 :                 read_unlock(&proc_subdir_lock);
     310         [ #  # ]:          0 :                 if (!dir_emit(ctx, de->name, de->namelen,
     311                 :          0 :                             de->low_ino, de->mode >> 12)) {
     312                 :          0 :                         pde_put(de);
     313                 :          0 :                         return 0;
     314                 :            :                 }
     315                 :          0 :                 ctx->pos++;
     316                 :          0 :                 read_lock(&proc_subdir_lock);
     317                 :          0 :                 next = pde_subdir_next(de);
     318                 :          0 :                 pde_put(de);
     319                 :          0 :                 de = next;
     320         [ #  # ]:          0 :         } while (de);
     321                 :          0 :         read_unlock(&proc_subdir_lock);
     322                 :          0 :         return 1;
     323                 :            : }
     324                 :            : 
     325                 :          0 : int proc_readdir(struct file *file, struct dir_context *ctx)
     326                 :            : {
     327                 :          0 :         struct inode *inode = file_inode(file);
     328                 :            : 
     329                 :          0 :         return proc_readdir_de(file, ctx, PDE(inode));
     330                 :            : }
     331                 :            : 
     332                 :            : /*
     333                 :            :  * These are the generic /proc directory operations. They
     334                 :            :  * use the in-memory "struct proc_dir_entry" tree to parse
     335                 :            :  * the /proc directory.
     336                 :            :  */
     337                 :            : static const struct file_operations proc_dir_operations = {
     338                 :            :         .llseek                 = generic_file_llseek,
     339                 :            :         .read                   = generic_read_dir,
     340                 :            :         .iterate_shared         = proc_readdir,
     341                 :            : };
     342                 :            : 
     343                 :            : /*
     344                 :            :  * proc directories can do almost nothing..
     345                 :            :  */
     346                 :            : static const struct inode_operations proc_dir_inode_operations = {
     347                 :            :         .lookup         = proc_lookup,
     348                 :            :         .getattr        = proc_getattr,
     349                 :            :         .setattr        = proc_notify_change,
     350                 :            : };
     351                 :            : 
     352                 :            : /* returns the registered entry, or frees dp and returns NULL on failure */
     353                 :      26664 : struct proc_dir_entry *proc_register(struct proc_dir_entry *dir,
     354                 :            :                 struct proc_dir_entry *dp)
     355                 :            : {
     356                 :      26664 :         if (proc_alloc_inum(&dp->low_ino))
     357                 :          0 :                 goto out_free_entry;
     358                 :            : 
     359                 :      26664 :         write_lock(&proc_subdir_lock);
     360                 :      26664 :         dp->parent = dir;
     361         [ -  + ]:      26664 :         if (pde_subdir_insert(dir, dp) == false) {
     362                 :          0 :                 WARN(1, "proc_dir_entry '%s/%s' already registered\n",
     363                 :            :                      dir->name, dp->name);
     364                 :          0 :                 write_unlock(&proc_subdir_lock);
     365                 :          0 :                 goto out_free_inum;
     366                 :            :         }
     367                 :      26664 :         dir->nlink++;
     368                 :      26664 :         write_unlock(&proc_subdir_lock);
     369                 :            : 
     370                 :      26664 :         return dp;
     371                 :            : out_free_inum:
     372                 :          0 :         proc_free_inum(dp->low_ino);
     373                 :          0 : out_free_entry:
     374                 :          0 :         pde_free(dp);
     375                 :          0 :         return NULL;
     376                 :            : }
     377                 :            : 
     378                 :      26664 : static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
     379                 :            :                                           const char *name,
     380                 :            :                                           umode_t mode,
     381                 :            :                                           nlink_t nlink)
     382                 :            : {
     383                 :      26664 :         struct proc_dir_entry *ent = NULL;
     384                 :      26664 :         const char *fn;
     385                 :      26664 :         struct qstr qstr;
     386                 :            : 
     387         [ -  + ]:      26664 :         if (xlate_proc_name(name, parent, &fn) != 0)
     388                 :          0 :                 goto out;
     389                 :      26664 :         qstr.name = fn;
     390                 :      26664 :         qstr.len = strlen(fn);
     391         [ -  + ]:      26664 :         if (qstr.len == 0 || qstr.len >= 256) {
     392                 :          0 :                 WARN(1, "name len %u\n", qstr.len);
     393                 :          0 :                 return NULL;
     394                 :            :         }
     395   [ +  +  -  + ]:      26664 :         if (qstr.len == 1 && fn[0] == '.') {
     396                 :          0 :                 WARN(1, "name '.'\n");
     397                 :          0 :                 return NULL;
     398                 :            :         }
     399   [ +  +  -  +  :      26664 :         if (qstr.len == 2 && fn[0] == '.' && fn[1] == '.') {
                   -  - ]
     400                 :          0 :                 WARN(1, "name '..'\n");
     401                 :          0 :                 return NULL;
     402                 :            :         }
     403   [ +  +  -  + ]:      26664 :         if (*parent == &proc_root && name_to_int(&qstr) != ~0U) {
     404                 :          0 :                 WARN(1, "create '/proc/%s' by hand\n", qstr.name);
     405                 :          0 :                 return NULL;
     406                 :            :         }
     407   [ +  +  -  + ]:      53328 :         if (is_empty_pde(*parent)) {
     408                 :          0 :                 WARN(1, "attempt to add to permanently empty directory");
     409                 :          0 :                 return NULL;
     410                 :            :         }
     411                 :            : 
     412                 :      26664 :         ent = kmem_cache_zalloc(proc_dir_entry_cache, GFP_KERNEL);
     413         [ -  + ]:      26664 :         if (!ent)
     414                 :          0 :                 goto out;
     415                 :            : 
     416         [ +  + ]:      26664 :         if (qstr.len + 1 <= SIZEOF_PDE_INLINE_NAME) {
     417                 :      21984 :                 ent->name = ent->inline_name;
     418                 :            :         } else {
     419         [ -  + ]:       4680 :                 ent->name = kmalloc(qstr.len + 1, GFP_KERNEL);
     420         [ -  + ]:       4680 :                 if (!ent->name) {
     421                 :          0 :                         pde_free(ent);
     422                 :          0 :                         return NULL;
     423                 :            :                 }
     424                 :            :         }
     425                 :            : 
     426                 :      26664 :         memcpy(ent->name, fn, qstr.len + 1);
     427                 :      26664 :         ent->namelen = qstr.len;
     428                 :      26664 :         ent->mode = mode;
     429                 :      26664 :         ent->nlink = nlink;
     430                 :      26664 :         ent->subdir = RB_ROOT;
     431                 :      26664 :         refcount_set(&ent->refcnt, 1);
     432                 :      26664 :         spin_lock_init(&ent->pde_unload_lock);
     433                 :      26664 :         INIT_LIST_HEAD(&ent->pde_openers);
     434                 :      26664 :         proc_set_user(ent, (*parent)->uid, (*parent)->gid);
     435                 :            : 
     436                 :      26664 :         ent->proc_dops = &proc_misc_dentry_ops;
     437                 :            : 
     438                 :            : out:
     439                 :            :         return ent;
     440                 :            : }
     441                 :            : 
     442                 :        312 : struct proc_dir_entry *proc_symlink(const char *name,
     443                 :            :                 struct proc_dir_entry *parent, const char *dest)
     444                 :            : {
     445                 :        312 :         struct proc_dir_entry *ent;
     446                 :            : 
     447                 :        312 :         ent = __proc_create(&parent, name,
     448                 :            :                           (S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO),1);
     449                 :            : 
     450         [ +  - ]:        312 :         if (ent) {
     451         [ -  + ]:        312 :                 ent->data = kmalloc((ent->size=strlen(dest))+1, GFP_KERNEL);
     452         [ +  - ]:        312 :                 if (ent->data) {
     453                 :        312 :                         strcpy((char*)ent->data,dest);
     454                 :        312 :                         ent->proc_iops = &proc_link_inode_operations;
     455                 :        312 :                         ent = proc_register(parent, ent);
     456                 :            :                 } else {
     457                 :          0 :                         pde_free(ent);
     458                 :          0 :                         ent = NULL;
     459                 :            :                 }
     460                 :            :         }
     461                 :        312 :         return ent;
     462                 :            : }
     463                 :            : EXPORT_SYMBOL(proc_symlink);
     464                 :            : 
     465                 :       4635 : struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode,
     466                 :            :                 struct proc_dir_entry *parent, void *data)
     467                 :            : {
     468                 :       4635 :         struct proc_dir_entry *ent;
     469                 :            : 
     470         [ +  + ]:       4635 :         if (mode == 0)
     471                 :       4479 :                 mode = S_IRUGO | S_IXUGO;
     472                 :            : 
     473                 :       4635 :         ent = __proc_create(&parent, name, S_IFDIR | mode, 2);
     474         [ +  - ]:       4635 :         if (ent) {
     475                 :       4635 :                 ent->data = data;
     476                 :       4635 :                 ent->proc_dir_ops = &proc_dir_operations;
     477                 :       4635 :                 ent->proc_iops = &proc_dir_inode_operations;
     478                 :       4635 :                 ent = proc_register(parent, ent);
     479                 :            :         }
     480                 :       4635 :         return ent;
     481                 :            : }
     482                 :            : EXPORT_SYMBOL_GPL(proc_mkdir_data);
     483                 :            : 
     484                 :        156 : struct proc_dir_entry *proc_mkdir_mode(const char *name, umode_t mode,
     485                 :            :                                        struct proc_dir_entry *parent)
     486                 :            : {
     487                 :        156 :         return proc_mkdir_data(name, mode, parent, NULL);
     488                 :            : }
     489                 :            : EXPORT_SYMBOL(proc_mkdir_mode);
     490                 :            : 
     491                 :       4167 : struct proc_dir_entry *proc_mkdir(const char *name,
     492                 :            :                 struct proc_dir_entry *parent)
     493                 :            : {
     494                 :       4167 :         return proc_mkdir_data(name, 0, parent, NULL);
     495                 :            : }
     496                 :            : EXPORT_SYMBOL(proc_mkdir);
     497                 :            : 
     498                 :         78 : struct proc_dir_entry *proc_create_mount_point(const char *name)
     499                 :            : {
     500                 :         78 :         umode_t mode = S_IFDIR | S_IRUGO | S_IXUGO;
     501                 :         78 :         struct proc_dir_entry *ent, *parent = NULL;
     502                 :            : 
     503                 :         78 :         ent = __proc_create(&parent, name, mode, 2);
     504         [ +  - ]:         78 :         if (ent) {
     505                 :         78 :                 ent->data = NULL;
     506                 :         78 :                 ent->proc_dir_ops = NULL;
     507                 :         78 :                 ent->proc_iops = NULL;
     508                 :         78 :                 ent = proc_register(parent, ent);
     509                 :            :         }
     510                 :         78 :         return ent;
     511                 :            : }
     512                 :            : EXPORT_SYMBOL(proc_create_mount_point);
     513                 :            : 
     514                 :      21639 : struct proc_dir_entry *proc_create_reg(const char *name, umode_t mode,
     515                 :            :                 struct proc_dir_entry **parent, void *data)
     516                 :            : {
     517                 :      21639 :         struct proc_dir_entry *p;
     518                 :            : 
     519         [ +  + ]:      21639 :         if ((mode & S_IFMT) == 0)
     520                 :      19221 :                 mode |= S_IFREG;
     521         [ +  + ]:      21639 :         if ((mode & S_IALLUGO) == 0)
     522                 :       3822 :                 mode |= S_IRUGO;
     523   [ -  +  +  - ]:      21639 :         if (WARN_ON_ONCE(!S_ISREG(mode)))
     524                 :            :                 return NULL;
     525                 :            : 
     526                 :      21639 :         p = __proc_create(parent, name, mode, 1);
     527         [ +  - ]:      21639 :         if (p) {
     528                 :      21639 :                 p->proc_iops = &proc_file_inode_operations;
     529                 :      21639 :                 p->data = data;
     530                 :            :         }
     531                 :            :         return p;
     532                 :            : }
     533                 :            : 
     534                 :       7098 : struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,
     535                 :            :                 struct proc_dir_entry *parent,
     536                 :            :                 const struct proc_ops *proc_ops, void *data)
     537                 :            : {
     538                 :       7098 :         struct proc_dir_entry *p;
     539                 :            : 
     540                 :       7098 :         p = proc_create_reg(name, mode, &parent, data);
     541         [ +  - ]:       7098 :         if (!p)
     542                 :            :                 return NULL;
     543                 :       7098 :         p->proc_ops = proc_ops;
     544                 :       7098 :         return proc_register(parent, p);
     545                 :            : }
     546                 :            : EXPORT_SYMBOL(proc_create_data);
     547                 :            :  
     548                 :       1950 : struct proc_dir_entry *proc_create(const char *name, umode_t mode,
     549                 :            :                                    struct proc_dir_entry *parent,
     550                 :            :                                    const struct proc_ops *proc_ops)
     551                 :            : {
     552                 :       1950 :         return proc_create_data(name, mode, parent, proc_ops, NULL);
     553                 :            : }
     554                 :            : EXPORT_SYMBOL(proc_create);
     555                 :            : 
     556                 :          0 : static int proc_seq_open(struct inode *inode, struct file *file)
     557                 :            : {
     558         [ #  # ]:          0 :         struct proc_dir_entry *de = PDE(inode);
     559                 :            : 
     560         [ #  # ]:          0 :         if (de->state_size)
     561                 :          0 :                 return seq_open_private(file, de->seq_ops, de->state_size);
     562                 :          0 :         return seq_open(file, de->seq_ops);
     563                 :            : }
     564                 :            : 
     565                 :          0 : static int proc_seq_release(struct inode *inode, struct file *file)
     566                 :            : {
     567         [ #  # ]:          0 :         struct proc_dir_entry *de = PDE(inode);
     568                 :            : 
     569         [ #  # ]:          0 :         if (de->state_size)
     570                 :          0 :                 return seq_release_private(inode, file);
     571                 :          0 :         return seq_release(inode, file);
     572                 :            : }
     573                 :            : 
     574                 :            : static const struct proc_ops proc_seq_ops = {
     575                 :            :         .proc_open      = proc_seq_open,
     576                 :            :         .proc_read      = seq_read,
     577                 :            :         .proc_lseek     = seq_lseek,
     578                 :            :         .proc_release   = proc_seq_release,
     579                 :            : };
     580                 :            : 
     581                 :       2730 : struct proc_dir_entry *proc_create_seq_private(const char *name, umode_t mode,
     582                 :            :                 struct proc_dir_entry *parent, const struct seq_operations *ops,
     583                 :            :                 unsigned int state_size, void *data)
     584                 :            : {
     585                 :       2730 :         struct proc_dir_entry *p;
     586                 :            : 
     587                 :       2730 :         p = proc_create_reg(name, mode, &parent, data);
     588         [ +  - ]:       2730 :         if (!p)
     589                 :            :                 return NULL;
     590                 :       2730 :         p->proc_ops = &proc_seq_ops;
     591                 :       2730 :         p->seq_ops = ops;
     592                 :       2730 :         p->state_size = state_size;
     593                 :       2730 :         return proc_register(parent, p);
     594                 :            : }
     595                 :            : EXPORT_SYMBOL(proc_create_seq_private);
     596                 :            : 
     597                 :       5325 : static int proc_single_open(struct inode *inode, struct file *file)
     598                 :            : {
     599                 :       5325 :         struct proc_dir_entry *de = PDE(inode);
     600                 :            : 
     601                 :       5325 :         return single_open(file, de->single_show, de->data);
     602                 :            : }
     603                 :            : 
     604                 :            : static const struct proc_ops proc_single_ops = {
     605                 :            :         .proc_open      = proc_single_open,
     606                 :            :         .proc_read      = seq_read,
     607                 :            :         .proc_lseek     = seq_lseek,
     608                 :            :         .proc_release   = single_release,
     609                 :            : };
     610                 :            : 
     611                 :       8145 : struct proc_dir_entry *proc_create_single_data(const char *name, umode_t mode,
     612                 :            :                 struct proc_dir_entry *parent,
     613                 :            :                 int (*show)(struct seq_file *, void *), void *data)
     614                 :            : {
     615                 :       8145 :         struct proc_dir_entry *p;
     616                 :            : 
     617                 :       8145 :         p = proc_create_reg(name, mode, &parent, data);
     618         [ +  - ]:       8145 :         if (!p)
     619                 :            :                 return NULL;
     620                 :       8145 :         p->proc_ops = &proc_single_ops;
     621                 :       8145 :         p->single_show = show;
     622                 :       8145 :         return proc_register(parent, p);
     623                 :            : }
     624                 :            : EXPORT_SYMBOL(proc_create_single_data);
     625                 :            : 
     626                 :       1326 : void proc_set_size(struct proc_dir_entry *de, loff_t size)
     627                 :            : {
     628                 :       1326 :         de->size = size;
     629                 :       1326 : }
     630                 :            : EXPORT_SYMBOL(proc_set_size);
     631                 :            : 
     632                 :      27444 : void proc_set_user(struct proc_dir_entry *de, kuid_t uid, kgid_t gid)
     633                 :            : {
     634                 :      27444 :         de->uid = uid;
     635                 :      26664 :         de->gid = gid;
     636                 :        780 : }
     637                 :            : EXPORT_SYMBOL(proc_set_user);
     638                 :            : 
     639                 :        813 : void pde_put(struct proc_dir_entry *pde)
     640                 :            : {
     641         [ +  + ]:        813 :         if (refcount_dec_and_test(&pde->refcnt)) {
     642                 :         78 :                 proc_free_inum(pde->low_ino);
     643                 :         78 :                 pde_free(pde);
     644                 :            :         }
     645                 :        813 : }
     646                 :            : 
     647                 :            : /*
     648                 :            :  * Remove a /proc entry and free it if it's not currently in use.
     649                 :            :  */
     650                 :          0 : void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
     651                 :            : {
     652                 :          0 :         struct proc_dir_entry *de = NULL;
     653                 :          0 :         const char *fn = name;
     654                 :          0 :         unsigned int len;
     655                 :            : 
     656                 :          0 :         write_lock(&proc_subdir_lock);
     657         [ #  # ]:          0 :         if (__xlate_proc_name(name, &parent, &fn) != 0) {
     658                 :          0 :                 write_unlock(&proc_subdir_lock);
     659                 :          0 :                 return;
     660                 :            :         }
     661                 :          0 :         len = strlen(fn);
     662                 :            : 
     663                 :          0 :         de = pde_subdir_find(parent, fn, len);
     664         [ #  # ]:          0 :         if (de) {
     665                 :          0 :                 rb_erase(&de->subdir_node, &parent->subdir);
     666         [ #  # ]:          0 :                 if (S_ISDIR(de->mode)) {
     667                 :          0 :                         parent->nlink--;
     668                 :            :                 }
     669                 :            :         }
     670                 :          0 :         write_unlock(&proc_subdir_lock);
     671         [ #  # ]:          0 :         if (!de) {
     672                 :          0 :                 WARN(1, "name '%s'\n", name);
     673                 :          0 :                 return;
     674                 :            :         }
     675                 :            : 
     676                 :          0 :         proc_entry_rundown(de);
     677                 :            : 
     678         [ #  # ]:          0 :         WARN(pde_subdir_first(de),
     679                 :            :              "%s: removing non-empty directory '%s/%s', leaking at least '%s'\n",
     680                 :            :              __func__, de->parent->name, de->name, pde_subdir_first(de)->name);
     681                 :          0 :         pde_put(de);
     682                 :            : }
     683                 :            : EXPORT_SYMBOL(remove_proc_entry);
     684                 :            : 
     685                 :         78 : int remove_proc_subtree(const char *name, struct proc_dir_entry *parent)
     686                 :            : {
     687                 :         78 :         struct proc_dir_entry *root = NULL, *de, *next;
     688                 :         78 :         const char *fn = name;
     689                 :         78 :         unsigned int len;
     690                 :            : 
     691                 :         78 :         write_lock(&proc_subdir_lock);
     692         [ -  + ]:         78 :         if (__xlate_proc_name(name, &parent, &fn) != 0) {
     693                 :          0 :                 write_unlock(&proc_subdir_lock);
     694                 :          0 :                 return -ENOENT;
     695                 :            :         }
     696                 :         78 :         len = strlen(fn);
     697                 :            : 
     698                 :         78 :         root = pde_subdir_find(parent, fn, len);
     699         [ -  + ]:         78 :         if (!root) {
     700                 :          0 :                 write_unlock(&proc_subdir_lock);
     701                 :          0 :                 return -ENOENT;
     702                 :            :         }
     703                 :         78 :         rb_erase(&root->subdir_node, &parent->subdir);
     704                 :            : 
     705                 :         78 :         de = root;
     706                 :         78 :         while (1) {
     707                 :         78 :                 next = pde_subdir_first(de);
     708         [ #  # ]:          0 :                 if (next) {
     709                 :          0 :                         rb_erase(&next->subdir_node, &de->subdir);
     710                 :          0 :                         de = next;
     711                 :          0 :                         continue;
     712                 :            :                 }
     713                 :         78 :                 next = de->parent;
     714         [ +  - ]:         78 :                 if (S_ISDIR(de->mode))
     715                 :         78 :                         next->nlink--;
     716                 :         78 :                 write_unlock(&proc_subdir_lock);
     717                 :            : 
     718                 :         78 :                 proc_entry_rundown(de);
     719         [ -  + ]:         78 :                 if (de == root)
     720                 :            :                         break;
     721                 :          0 :                 pde_put(de);
     722                 :            : 
     723                 :          0 :                 write_lock(&proc_subdir_lock);
     724                 :          0 :                 de = next;
     725                 :            :         }
     726                 :         78 :         pde_put(root);
     727                 :         78 :         return 0;
     728                 :            : }
     729                 :            : EXPORT_SYMBOL(remove_proc_subtree);
     730                 :            : 
     731                 :          0 : void *proc_get_parent_data(const struct inode *inode)
     732                 :            : {
     733                 :          0 :         struct proc_dir_entry *de = PDE(inode);
     734                 :          0 :         return de->parent->data;
     735                 :            : }
     736                 :            : EXPORT_SYMBOL_GPL(proc_get_parent_data);
     737                 :            : 
     738                 :         78 : void proc_remove(struct proc_dir_entry *de)
     739                 :            : {
     740         [ +  - ]:         78 :         if (de)
     741                 :         78 :                 remove_proc_subtree(de->name, de->parent);
     742                 :         78 : }
     743                 :            : EXPORT_SYMBOL(proc_remove);
     744                 :            : 
     745                 :          0 : void *PDE_DATA(const struct inode *inode)
     746                 :            : {
     747                 :          0 :         return __PDE_DATA(inode);
     748                 :            : }
     749                 :            : EXPORT_SYMBOL(PDE_DATA);
     750                 :            : 
     751                 :            : /*
     752                 :            :  * Pull a user buffer into memory and pass it to the file's write handler if
     753                 :            :  * one is supplied.  The ->write() method is permitted to modify the
     754                 :            :  * kernel-side buffer.
     755                 :            :  */
     756                 :          0 : ssize_t proc_simple_write(struct file *f, const char __user *ubuf, size_t size,
     757                 :            :                           loff_t *_pos)
     758                 :            : {
     759         [ #  # ]:          0 :         struct proc_dir_entry *pde = PDE(file_inode(f));
     760                 :          0 :         char *buf;
     761                 :          0 :         int ret;
     762                 :            : 
     763         [ #  # ]:          0 :         if (!pde->write)
     764                 :            :                 return -EACCES;
     765         [ #  # ]:          0 :         if (size == 0 || size > PAGE_SIZE - 1)
     766                 :            :                 return -EINVAL;
     767                 :          0 :         buf = memdup_user_nul(ubuf, size);
     768         [ #  # ]:          0 :         if (IS_ERR(buf))
     769                 :          0 :                 return PTR_ERR(buf);
     770                 :          0 :         ret = pde->write(f, buf, size);
     771                 :          0 :         kfree(buf);
     772         [ #  # ]:          0 :         return ret == 0 ? size : ret;
     773                 :            : }

Generated by: LCOV version 1.14