LCOV - code coverage report
Current view: top level - fs/proc - root.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 86 153 56.2 %
Date: 2021-04-22 12:43:58 Functions: 10 14 71.4 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  *  linux/fs/proc/root.c
       4             :  *
       5             :  *  Copyright (C) 1991, 1992 Linus Torvalds
       6             :  *
       7             :  *  proc root directory handling functions
       8             :  */
       9             : 
      10             : #include <linux/uaccess.h>
      11             : 
      12             : #include <linux/errno.h>
      13             : #include <linux/time.h>
      14             : #include <linux/proc_fs.h>
      15             : #include <linux/stat.h>
      16             : #include <linux/init.h>
      17             : #include <linux/sched.h>
      18             : #include <linux/sched/stat.h>
      19             : #include <linux/module.h>
      20             : #include <linux/bitops.h>
      21             : #include <linux/user_namespace.h>
      22             : #include <linux/fs_context.h>
      23             : #include <linux/mount.h>
      24             : #include <linux/pid_namespace.h>
      25             : #include <linux/fs_parser.h>
      26             : #include <linux/cred.h>
      27             : #include <linux/magic.h>
      28             : #include <linux/slab.h>
      29             : 
      30             : #include "internal.h"
      31             : 
      32             : struct proc_fs_context {
      33             :         struct pid_namespace    *pid_ns;
      34             :         unsigned int            mask;
      35             :         enum proc_hidepid       hidepid;
      36             :         int                     gid;
      37             :         enum proc_pidonly       pidonly;
      38             : };
      39             : 
      40             : enum proc_param {
      41             :         Opt_gid,
      42             :         Opt_hidepid,
      43             :         Opt_subset,
      44             : };
      45             : 
      46             : static const struct fs_parameter_spec proc_fs_parameters[] = {
      47             :         fsparam_u32("gid",    Opt_gid),
      48             :         fsparam_string("hidepid",     Opt_hidepid),
      49             :         fsparam_string("subset",      Opt_subset),
      50             :         {}
      51             : };
      52             : 
      53           0 : static inline int valid_hidepid(unsigned int value)
      54             : {
      55           0 :         return (value == HIDEPID_OFF ||
      56           0 :                 value == HIDEPID_NO_ACCESS ||
      57           0 :                 value == HIDEPID_INVISIBLE ||
      58           0 :                 value == HIDEPID_NOT_PTRACEABLE);
      59             : }
      60             : 
      61           0 : static int proc_parse_hidepid_param(struct fs_context *fc, struct fs_parameter *param)
      62             : {
      63           0 :         struct proc_fs_context *ctx = fc->fs_private;
      64           0 :         struct fs_parameter_spec hidepid_u32_spec = fsparam_u32("hidepid", Opt_hidepid);
      65           0 :         struct fs_parse_result result;
      66           0 :         int base = (unsigned long)hidepid_u32_spec.data;
      67             : 
      68           0 :         if (param->type != fs_value_is_string)
      69           0 :                 return invalf(fc, "proc: unexpected type of hidepid value\n");
      70             : 
      71           0 :         if (!kstrtouint(param->string, base, &result.uint_32)) {
      72           0 :                 if (!valid_hidepid(result.uint_32))
      73           0 :                         return invalf(fc, "proc: unknown value of hidepid - %s\n", param->string);
      74           0 :                 ctx->hidepid = result.uint_32;
      75           0 :                 return 0;
      76             :         }
      77             : 
      78           0 :         if (!strcmp(param->string, "off"))
      79           0 :                 ctx->hidepid = HIDEPID_OFF;
      80           0 :         else if (!strcmp(param->string, "noaccess"))
      81           0 :                 ctx->hidepid = HIDEPID_NO_ACCESS;
      82           0 :         else if (!strcmp(param->string, "invisible"))
      83           0 :                 ctx->hidepid = HIDEPID_INVISIBLE;
      84           0 :         else if (!strcmp(param->string, "ptraceable"))
      85           0 :                 ctx->hidepid = HIDEPID_NOT_PTRACEABLE;
      86             :         else
      87           0 :                 return invalf(fc, "proc: unknown value of hidepid - %s\n", param->string);
      88             : 
      89             :         return 0;
      90             : }
      91             : 
      92           0 : static int proc_parse_subset_param(struct fs_context *fc, char *value)
      93             : {
      94           0 :         struct proc_fs_context *ctx = fc->fs_private;
      95             : 
      96           0 :         while (value) {
      97           0 :                 char *ptr = strchr(value, ',');
      98             : 
      99           0 :                 if (ptr != NULL)
     100           0 :                         *ptr++ = '\0';
     101             : 
     102           0 :                 if (*value != '\0') {
     103           0 :                         if (!strcmp(value, "pid")) {
     104           0 :                                 ctx->pidonly = PROC_PIDONLY_ON;
     105             :                         } else {
     106           0 :                                 return invalf(fc, "proc: unsupported subset option - %s\n", value);
     107             :                         }
     108             :                 }
     109             :                 value = ptr;
     110             :         }
     111             : 
     112             :         return 0;
     113             : }
     114             : 
     115           2 : static int proc_parse_param(struct fs_context *fc, struct fs_parameter *param)
     116             : {
     117           2 :         struct proc_fs_context *ctx = fc->fs_private;
     118           2 :         struct fs_parse_result result;
     119           2 :         int opt;
     120             : 
     121           2 :         opt = fs_parse(fc, proc_fs_parameters, param, &result);
     122           2 :         if (opt < 0)
     123             :                 return opt;
     124             : 
     125           0 :         switch (opt) {
     126           0 :         case Opt_gid:
     127           0 :                 ctx->gid = result.uint_32;
     128           0 :                 break;
     129             : 
     130           0 :         case Opt_hidepid:
     131           0 :                 if (proc_parse_hidepid_param(fc, param))
     132             :                         return -EINVAL;
     133             :                 break;
     134             : 
     135           0 :         case Opt_subset:
     136           0 :                 if (proc_parse_subset_param(fc, param->string) < 0)
     137             :                         return -EINVAL;
     138             :                 break;
     139             : 
     140             :         default:
     141             :                 return -EINVAL;
     142             :         }
     143             : 
     144           0 :         ctx->mask |= 1 << opt;
     145           0 :         return 0;
     146             : }
     147             : 
     148           2 : static void proc_apply_options(struct proc_fs_info *fs_info,
     149             :                                struct fs_context *fc,
     150             :                                struct user_namespace *user_ns)
     151             : {
     152           2 :         struct proc_fs_context *ctx = fc->fs_private;
     153             : 
     154           2 :         if (ctx->mask & (1 << Opt_gid))
     155           0 :                 fs_info->pid_gid = make_kgid(user_ns, ctx->gid);
     156           2 :         if (ctx->mask & (1 << Opt_hidepid))
     157           0 :                 fs_info->hide_pid = ctx->hidepid;
     158           2 :         if (ctx->mask & (1 << Opt_subset))
     159           0 :                 fs_info->pidonly = ctx->pidonly;
     160           2 : }
     161             : 
     162           2 : static int proc_fill_super(struct super_block *s, struct fs_context *fc)
     163             : {
     164           2 :         struct proc_fs_context *ctx = fc->fs_private;
     165           2 :         struct inode *root_inode;
     166           2 :         struct proc_fs_info *fs_info;
     167           2 :         int ret;
     168             : 
     169           2 :         fs_info = kzalloc(sizeof(*fs_info), GFP_KERNEL);
     170           2 :         if (!fs_info)
     171             :                 return -ENOMEM;
     172             : 
     173           2 :         fs_info->pid_ns = get_pid_ns(ctx->pid_ns);
     174           2 :         proc_apply_options(fs_info, fc, current_user_ns());
     175             : 
     176             :         /* User space would break if executables or devices appear on proc */
     177           2 :         s->s_iflags |= SB_I_USERNS_VISIBLE | SB_I_NOEXEC | SB_I_NODEV;
     178           2 :         s->s_flags |= SB_NODIRATIME | SB_NOSUID | SB_NOEXEC;
     179           2 :         s->s_blocksize = 1024;
     180           2 :         s->s_blocksize_bits = 10;
     181           2 :         s->s_magic = PROC_SUPER_MAGIC;
     182           2 :         s->s_op = &proc_sops;
     183           2 :         s->s_time_gran = 1;
     184           2 :         s->s_fs_info = fs_info;
     185             : 
     186             :         /*
     187             :          * procfs isn't actually a stacking filesystem; however, there is
     188             :          * too much magic going on inside it to permit stacking things on
     189             :          * top of it
     190             :          */
     191           2 :         s->s_stack_depth = FILESYSTEM_MAX_STACK_DEPTH;
     192             : 
     193             :         /* procfs dentries and inodes don't require IO to create */
     194           2 :         s->s_shrink.seeks = 0;
     195             : 
     196           2 :         pde_get(&proc_root);
     197           2 :         root_inode = proc_get_inode(s, &proc_root);
     198           2 :         if (!root_inode) {
     199           0 :                 pr_err("proc_fill_super: get root inode failed\n");
     200           0 :                 return -ENOMEM;
     201             :         }
     202             : 
     203           2 :         s->s_root = d_make_root(root_inode);
     204           2 :         if (!s->s_root) {
     205           0 :                 pr_err("proc_fill_super: allocate dentry failed\n");
     206           0 :                 return -ENOMEM;
     207             :         }
     208             : 
     209           2 :         ret = proc_setup_self(s);
     210           2 :         if (ret) {
     211             :                 return ret;
     212             :         }
     213           2 :         return proc_setup_thread_self(s);
     214             : }
     215             : 
     216           0 : static int proc_reconfigure(struct fs_context *fc)
     217             : {
     218           0 :         struct super_block *sb = fc->root->d_sb;
     219           0 :         struct proc_fs_info *fs_info = proc_sb_info(sb);
     220             : 
     221           0 :         sync_filesystem(sb);
     222             : 
     223           0 :         proc_apply_options(fs_info, fc, current_user_ns());
     224           0 :         return 0;
     225             : }
     226             : 
     227           2 : static int proc_get_tree(struct fs_context *fc)
     228             : {
     229           2 :         return get_tree_nodev(fc, proc_fill_super);
     230             : }
     231             : 
     232           2 : static void proc_fs_context_free(struct fs_context *fc)
     233             : {
     234           2 :         struct proc_fs_context *ctx = fc->fs_private;
     235             : 
     236           2 :         put_pid_ns(ctx->pid_ns);
     237           2 :         kfree(ctx);
     238           2 : }
     239             : 
     240             : static const struct fs_context_operations proc_fs_context_ops = {
     241             :         .free           = proc_fs_context_free,
     242             :         .parse_param    = proc_parse_param,
     243             :         .get_tree       = proc_get_tree,
     244             :         .reconfigure    = proc_reconfigure,
     245             : };
     246             : 
     247           2 : static int proc_init_fs_context(struct fs_context *fc)
     248             : {
     249           2 :         struct proc_fs_context *ctx;
     250             : 
     251           2 :         ctx = kzalloc(sizeof(struct proc_fs_context), GFP_KERNEL);
     252           2 :         if (!ctx)
     253             :                 return -ENOMEM;
     254             : 
     255           2 :         ctx->pid_ns = get_pid_ns(task_active_pid_ns(current));
     256           2 :         put_user_ns(fc->user_ns);
     257           2 :         fc->user_ns = get_user_ns(ctx->pid_ns->user_ns);
     258           2 :         fc->fs_private = ctx;
     259           2 :         fc->ops = &proc_fs_context_ops;
     260           2 :         return 0;
     261             : }
     262             : 
     263           1 : static void proc_kill_sb(struct super_block *sb)
     264             : {
     265           1 :         struct proc_fs_info *fs_info = proc_sb_info(sb);
     266             : 
     267           1 :         if (!fs_info) {
     268           0 :                 kill_anon_super(sb);
     269           0 :                 return;
     270             :         }
     271             : 
     272           1 :         dput(fs_info->proc_self);
     273           1 :         dput(fs_info->proc_thread_self);
     274             : 
     275           1 :         kill_anon_super(sb);
     276           1 :         put_pid_ns(fs_info->pid_ns);
     277           1 :         kfree(fs_info);
     278             : }
     279             : 
     280             : static struct file_system_type proc_fs_type = {
     281             :         .name                   = "proc",
     282             :         .init_fs_context        = proc_init_fs_context,
     283             :         .parameters             = proc_fs_parameters,
     284             :         .kill_sb                = proc_kill_sb,
     285             :         .fs_flags               = FS_USERNS_MOUNT | FS_DISALLOW_NOTIFY_PERM,
     286             : };
     287             : 
     288           1 : void __init proc_root_init(void)
     289             : {
     290           1 :         proc_init_kmemcache();
     291           1 :         set_proc_pid_nlink();
     292           1 :         proc_self_init();
     293           1 :         proc_thread_self_init();
     294           1 :         proc_symlink("mounts", NULL, "self/mounts");
     295             : 
     296           1 :         proc_net_init();
     297           1 :         proc_mkdir("fs", NULL);
     298           1 :         proc_mkdir("driver", NULL);
     299           1 :         proc_create_mount_point("fs/nfsd"); /* somewhere for the nfsd filesystem to be mounted */
     300             : #if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE)
     301             :         /* just give it a mountpoint */
     302             :         proc_create_mount_point("openprom");
     303             : #endif
     304           1 :         proc_tty_init();
     305           1 :         proc_mkdir("bus", NULL);
     306           1 :         proc_sys_init();
     307             : 
     308           1 :         register_filesystem(&proc_fs_type);
     309           1 : }
     310             : 
     311         153 : static int proc_root_getattr(struct user_namespace *mnt_userns,
     312             :                              const struct path *path, struct kstat *stat,
     313             :                              u32 request_mask, unsigned int query_flags)
     314             : {
     315         153 :         generic_fillattr(&init_user_ns, d_inode(path->dentry), stat);
     316         153 :         stat->nlink = proc_root.nlink + nr_processes();
     317         153 :         return 0;
     318             : }
     319             : 
     320         337 : static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, unsigned int flags)
     321             : {
     322         337 :         if (!proc_pid_lookup(dentry, flags))
     323             :                 return NULL;
     324             : 
     325         110 :         return proc_lookup(dir, dentry, flags);
     326             : }
     327             : 
     328           0 : static int proc_root_readdir(struct file *file, struct dir_context *ctx)
     329             : {
     330           0 :         if (ctx->pos < FIRST_PROCESS_ENTRY) {
     331           0 :                 int error = proc_readdir(file, ctx);
     332           0 :                 if (unlikely(error <= 0))
     333             :                         return error;
     334           0 :                 ctx->pos = FIRST_PROCESS_ENTRY;
     335             :         }
     336             : 
     337           0 :         return proc_pid_readdir(file, ctx);
     338             : }
     339             : 
     340             : /*
     341             :  * The root /proc directory is special, as it has the
     342             :  * <pid> directories. Thus we don't use the generic
     343             :  * directory handling functions for that..
     344             :  */
     345             : static const struct file_operations proc_root_operations = {
     346             :         .read            = generic_read_dir,
     347             :         .iterate_shared  = proc_root_readdir,
     348             :         .llseek         = generic_file_llseek,
     349             : };
     350             : 
     351             : /*
     352             :  * proc root can do almost nothing..
     353             :  */
     354             : static const struct inode_operations proc_root_inode_operations = {
     355             :         .lookup         = proc_root_lookup,
     356             :         .getattr        = proc_root_getattr,
     357             : };
     358             : 
     359             : /*
     360             :  * This is the root "inode" in the /proc tree..
     361             :  */
     362             : struct proc_dir_entry proc_root = {
     363             :         .low_ino        = PROC_ROOT_INO, 
     364             :         .namelen        = 5, 
     365             :         .mode           = S_IFDIR | S_IRUGO | S_IXUGO, 
     366             :         .nlink          = 2, 
     367             :         .refcnt         = REFCOUNT_INIT(1),
     368             :         .proc_iops      = &proc_root_inode_operations, 
     369             :         .proc_dir_ops   = &proc_root_operations,
     370             :         .parent         = &proc_root,
     371             :         .subdir         = RB_ROOT,
     372             :         .name           = "/proc",
     373             : };

Generated by: LCOV version 1.14