LCOV - code coverage report
Current view: top level - fs/proc - generic.c (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_real_modules_combined.info Lines: 217 306 70.9 %
Date: 2020-09-30 20:25:40 Functions: 32 39 82.1 %
Branches: 82 168 48.8 %

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

Generated by: LCOV version 1.14