LCOV - code coverage report
Current view: top level - fs/proc - generic.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 146 355 41.1 %
Date: 2022-12-09 01:23:36 Functions: 16 39 41.0 %

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

Generated by: LCOV version 1.14