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