1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * linux/fs/proc/root.c
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Copyright (C) 1991, 1992 Linus Torvalds
61da177e4SLinus Torvalds *
71da177e4SLinus Torvalds * proc root directory handling functions
81da177e4SLinus Torvalds */
91da177e4SLinus Torvalds #include <linux/errno.h>
101da177e4SLinus Torvalds #include <linux/time.h>
111da177e4SLinus Torvalds #include <linux/proc_fs.h>
121da177e4SLinus Torvalds #include <linux/stat.h>
131da177e4SLinus Torvalds #include <linux/init.h>
14914e2637SAl Viro #include <linux/sched.h>
1503441a34SIngo Molnar #include <linux/sched/stat.h>
161da177e4SLinus Torvalds #include <linux/module.h>
171da177e4SLinus Torvalds #include <linux/bitops.h>
1887a8ebd6SEric W. Biederman #include <linux/user_namespace.h>
1966f592e2SDavid Howells #include <linux/fs_context.h>
20f6c7a1f3SEric W. Biederman #include <linux/mount.h>
2107543f5cSPavel Emelyanov #include <linux/pid_namespace.h>
2266f592e2SDavid Howells #include <linux/fs_parser.h>
235b825c3aSIngo Molnar #include <linux/cred.h>
2460a3c3a5SDavid Howells #include <linux/magic.h>
2566f592e2SDavid Howells #include <linux/slab.h>
261da177e4SLinus Torvalds
27fee781e6SAdrian Bunk #include "internal.h"
28fee781e6SAdrian Bunk
2966f592e2SDavid Howells struct proc_fs_context {
3066f592e2SDavid Howells struct pid_namespace *pid_ns;
3166f592e2SDavid Howells unsigned int mask;
32e61bb8b3SAlexey Gladkov enum proc_hidepid hidepid;
3366f592e2SDavid Howells int gid;
34e61bb8b3SAlexey Gladkov enum proc_pidonly pidonly;
3597412950SVasiliy Kulikov };
3697412950SVasiliy Kulikov
3766f592e2SDavid Howells enum proc_param {
3866f592e2SDavid Howells Opt_gid,
3966f592e2SDavid Howells Opt_hidepid,
406814ef2dSAlexey Gladkov Opt_subset,
4197412950SVasiliy Kulikov };
4297412950SVasiliy Kulikov
43d7167b14SAl Viro static const struct fs_parameter_spec proc_fs_parameters[] = {
4466f592e2SDavid Howells fsparam_u32("gid", Opt_gid),
451c6c4d11SAlexey Gladkov fsparam_string("hidepid", Opt_hidepid),
466814ef2dSAlexey Gladkov fsparam_string("subset", Opt_subset),
4766f592e2SDavid Howells {}
4866f592e2SDavid Howells };
4966f592e2SDavid Howells
valid_hidepid(unsigned int value)5024a71ce5SAlexey Gladkov static inline int valid_hidepid(unsigned int value)
5124a71ce5SAlexey Gladkov {
5224a71ce5SAlexey Gladkov return (value == HIDEPID_OFF ||
5324a71ce5SAlexey Gladkov value == HIDEPID_NO_ACCESS ||
5424a71ce5SAlexey Gladkov value == HIDEPID_INVISIBLE ||
5524a71ce5SAlexey Gladkov value == HIDEPID_NOT_PTRACEABLE);
5624a71ce5SAlexey Gladkov }
5724a71ce5SAlexey Gladkov
proc_parse_hidepid_param(struct fs_context * fc,struct fs_parameter * param)581c6c4d11SAlexey Gladkov static int proc_parse_hidepid_param(struct fs_context *fc, struct fs_parameter *param)
591c6c4d11SAlexey Gladkov {
601c6c4d11SAlexey Gladkov struct proc_fs_context *ctx = fc->fs_private;
611c6c4d11SAlexey Gladkov struct fs_parameter_spec hidepid_u32_spec = fsparam_u32("hidepid", Opt_hidepid);
621c6c4d11SAlexey Gladkov struct fs_parse_result result;
631c6c4d11SAlexey Gladkov int base = (unsigned long)hidepid_u32_spec.data;
641c6c4d11SAlexey Gladkov
651c6c4d11SAlexey Gladkov if (param->type != fs_value_is_string)
661c6c4d11SAlexey Gladkov return invalf(fc, "proc: unexpected type of hidepid value\n");
671c6c4d11SAlexey Gladkov
681c6c4d11SAlexey Gladkov if (!kstrtouint(param->string, base, &result.uint_32)) {
691c6c4d11SAlexey Gladkov if (!valid_hidepid(result.uint_32))
701c6c4d11SAlexey Gladkov return invalf(fc, "proc: unknown value of hidepid - %s\n", param->string);
711c6c4d11SAlexey Gladkov ctx->hidepid = result.uint_32;
721c6c4d11SAlexey Gladkov return 0;
731c6c4d11SAlexey Gladkov }
741c6c4d11SAlexey Gladkov
751c6c4d11SAlexey Gladkov if (!strcmp(param->string, "off"))
761c6c4d11SAlexey Gladkov ctx->hidepid = HIDEPID_OFF;
771c6c4d11SAlexey Gladkov else if (!strcmp(param->string, "noaccess"))
781c6c4d11SAlexey Gladkov ctx->hidepid = HIDEPID_NO_ACCESS;
791c6c4d11SAlexey Gladkov else if (!strcmp(param->string, "invisible"))
801c6c4d11SAlexey Gladkov ctx->hidepid = HIDEPID_INVISIBLE;
811c6c4d11SAlexey Gladkov else if (!strcmp(param->string, "ptraceable"))
821c6c4d11SAlexey Gladkov ctx->hidepid = HIDEPID_NOT_PTRACEABLE;
831c6c4d11SAlexey Gladkov else
841c6c4d11SAlexey Gladkov return invalf(fc, "proc: unknown value of hidepid - %s\n", param->string);
851c6c4d11SAlexey Gladkov
861c6c4d11SAlexey Gladkov return 0;
871c6c4d11SAlexey Gladkov }
881c6c4d11SAlexey Gladkov
proc_parse_subset_param(struct fs_context * fc,char * value)896814ef2dSAlexey Gladkov static int proc_parse_subset_param(struct fs_context *fc, char *value)
906814ef2dSAlexey Gladkov {
916814ef2dSAlexey Gladkov struct proc_fs_context *ctx = fc->fs_private;
926814ef2dSAlexey Gladkov
936814ef2dSAlexey Gladkov while (value) {
946814ef2dSAlexey Gladkov char *ptr = strchr(value, ',');
956814ef2dSAlexey Gladkov
966814ef2dSAlexey Gladkov if (ptr != NULL)
976814ef2dSAlexey Gladkov *ptr++ = '\0';
986814ef2dSAlexey Gladkov
996814ef2dSAlexey Gladkov if (*value != '\0') {
1006814ef2dSAlexey Gladkov if (!strcmp(value, "pid")) {
1016814ef2dSAlexey Gladkov ctx->pidonly = PROC_PIDONLY_ON;
1026814ef2dSAlexey Gladkov } else {
1036814ef2dSAlexey Gladkov return invalf(fc, "proc: unsupported subset option - %s\n", value);
1046814ef2dSAlexey Gladkov }
1056814ef2dSAlexey Gladkov }
1066814ef2dSAlexey Gladkov value = ptr;
1076814ef2dSAlexey Gladkov }
1086814ef2dSAlexey Gladkov
1096814ef2dSAlexey Gladkov return 0;
1106814ef2dSAlexey Gladkov }
1116814ef2dSAlexey Gladkov
proc_parse_param(struct fs_context * fc,struct fs_parameter * param)11266f592e2SDavid Howells static int proc_parse_param(struct fs_context *fc, struct fs_parameter *param)
11397412950SVasiliy Kulikov {
11466f592e2SDavid Howells struct proc_fs_context *ctx = fc->fs_private;
11566f592e2SDavid Howells struct fs_parse_result result;
11666f592e2SDavid Howells int opt;
11797412950SVasiliy Kulikov
118d7167b14SAl Viro opt = fs_parse(fc, proc_fs_parameters, param, &result);
11966f592e2SDavid Howells if (opt < 0)
12066f592e2SDavid Howells return opt;
12197412950SVasiliy Kulikov
12266f592e2SDavid Howells switch (opt) {
1230499680aSVasiliy Kulikov case Opt_gid:
12466f592e2SDavid Howells ctx->gid = result.uint_32;
1250499680aSVasiliy Kulikov break;
12666f592e2SDavid Howells
1270499680aSVasiliy Kulikov case Opt_hidepid:
1281c6c4d11SAlexey Gladkov if (proc_parse_hidepid_param(fc, param))
1291c6c4d11SAlexey Gladkov return -EINVAL;
1300499680aSVasiliy Kulikov break;
13166f592e2SDavid Howells
1326814ef2dSAlexey Gladkov case Opt_subset:
1336814ef2dSAlexey Gladkov if (proc_parse_subset_param(fc, param->string) < 0)
1346814ef2dSAlexey Gladkov return -EINVAL;
1356814ef2dSAlexey Gladkov break;
1366814ef2dSAlexey Gladkov
13797412950SVasiliy Kulikov default:
13866f592e2SDavid Howells return -EINVAL;
13966f592e2SDavid Howells }
14066f592e2SDavid Howells
14166f592e2SDavid Howells ctx->mask |= 1 << opt;
14297412950SVasiliy Kulikov return 0;
14397412950SVasiliy Kulikov }
14497412950SVasiliy Kulikov
proc_apply_options(struct proc_fs_info * fs_info,struct fs_context * fc,struct user_namespace * user_ns)145fa10fed3SAlexey Gladkov static void proc_apply_options(struct proc_fs_info *fs_info,
14666f592e2SDavid Howells struct fs_context *fc,
14766f592e2SDavid Howells struct user_namespace *user_ns)
14897412950SVasiliy Kulikov {
14966f592e2SDavid Howells struct proc_fs_context *ctx = fc->fs_private;
15066f592e2SDavid Howells
15166f592e2SDavid Howells if (ctx->mask & (1 << Opt_gid))
152fa10fed3SAlexey Gladkov fs_info->pid_gid = make_kgid(user_ns, ctx->gid);
15366f592e2SDavid Howells if (ctx->mask & (1 << Opt_hidepid))
154fa10fed3SAlexey Gladkov fs_info->hide_pid = ctx->hidepid;
1556814ef2dSAlexey Gladkov if (ctx->mask & (1 << Opt_subset))
1566814ef2dSAlexey Gladkov fs_info->pidonly = ctx->pidonly;
15766f592e2SDavid Howells }
15866f592e2SDavid Howells
proc_fill_super(struct super_block * s,struct fs_context * fc)15966f592e2SDavid Howells static int proc_fill_super(struct super_block *s, struct fs_context *fc)
16066f592e2SDavid Howells {
161fa10fed3SAlexey Gladkov struct proc_fs_context *ctx = fc->fs_private;
16260a3c3a5SDavid Howells struct inode *root_inode;
163fa10fed3SAlexey Gladkov struct proc_fs_info *fs_info;
16460a3c3a5SDavid Howells int ret;
16560a3c3a5SDavid Howells
166fa10fed3SAlexey Gladkov fs_info = kzalloc(sizeof(*fs_info), GFP_KERNEL);
167fa10fed3SAlexey Gladkov if (!fs_info)
168fa10fed3SAlexey Gladkov return -ENOMEM;
169fa10fed3SAlexey Gladkov
170fa10fed3SAlexey Gladkov fs_info->pid_ns = get_pid_ns(ctx->pid_ns);
171fa10fed3SAlexey Gladkov proc_apply_options(fs_info, fc, current_user_ns());
17260a3c3a5SDavid Howells
17360a3c3a5SDavid Howells /* User space would break if executables or devices appear on proc */
17460a3c3a5SDavid Howells s->s_iflags |= SB_I_USERNS_VISIBLE | SB_I_NOEXEC | SB_I_NODEV;
17560a3c3a5SDavid Howells s->s_flags |= SB_NODIRATIME | SB_NOSUID | SB_NOEXEC;
17660a3c3a5SDavid Howells s->s_blocksize = 1024;
17760a3c3a5SDavid Howells s->s_blocksize_bits = 10;
17860a3c3a5SDavid Howells s->s_magic = PROC_SUPER_MAGIC;
17960a3c3a5SDavid Howells s->s_op = &proc_sops;
18060a3c3a5SDavid Howells s->s_time_gran = 1;
181fa10fed3SAlexey Gladkov s->s_fs_info = fs_info;
18260a3c3a5SDavid Howells
18360a3c3a5SDavid Howells /*
18460a3c3a5SDavid Howells * procfs isn't actually a stacking filesystem; however, there is
18560a3c3a5SDavid Howells * too much magic going on inside it to permit stacking things on
18660a3c3a5SDavid Howells * top of it
18760a3c3a5SDavid Howells */
18860a3c3a5SDavid Howells s->s_stack_depth = FILESYSTEM_MAX_STACK_DEPTH;
18960a3c3a5SDavid Howells
19060a3c3a5SDavid Howells /* procfs dentries and inodes don't require IO to create */
19160a3c3a5SDavid Howells s->s_shrink.seeks = 0;
19260a3c3a5SDavid Howells
19360a3c3a5SDavid Howells pde_get(&proc_root);
19460a3c3a5SDavid Howells root_inode = proc_get_inode(s, &proc_root);
19560a3c3a5SDavid Howells if (!root_inode) {
19660a3c3a5SDavid Howells pr_err("proc_fill_super: get root inode failed\n");
19760a3c3a5SDavid Howells return -ENOMEM;
19860a3c3a5SDavid Howells }
19960a3c3a5SDavid Howells
20060a3c3a5SDavid Howells s->s_root = d_make_root(root_inode);
20160a3c3a5SDavid Howells if (!s->s_root) {
20260a3c3a5SDavid Howells pr_err("proc_fill_super: allocate dentry failed\n");
20360a3c3a5SDavid Howells return -ENOMEM;
20460a3c3a5SDavid Howells }
20560a3c3a5SDavid Howells
20660a3c3a5SDavid Howells ret = proc_setup_self(s);
20760a3c3a5SDavid Howells if (ret) {
20860a3c3a5SDavid Howells return ret;
20960a3c3a5SDavid Howells }
21060a3c3a5SDavid Howells return proc_setup_thread_self(s);
21160a3c3a5SDavid Howells }
21260a3c3a5SDavid Howells
proc_reconfigure(struct fs_context * fc)21366f592e2SDavid Howells static int proc_reconfigure(struct fs_context *fc)
21497412950SVasiliy Kulikov {
21566f592e2SDavid Howells struct super_block *sb = fc->root->d_sb;
216fa10fed3SAlexey Gladkov struct proc_fs_info *fs_info = proc_sb_info(sb);
21702b9984dSTheodore Ts'o
21802b9984dSTheodore Ts'o sync_filesystem(sb);
21966f592e2SDavid Howells
220fa10fed3SAlexey Gladkov proc_apply_options(fs_info, fc, current_user_ns());
22166f592e2SDavid Howells return 0;
22297412950SVasiliy Kulikov }
22397412950SVasiliy Kulikov
proc_get_tree(struct fs_context * fc)22466f592e2SDavid Howells static int proc_get_tree(struct fs_context *fc)
2251da177e4SLinus Torvalds {
226fa10fed3SAlexey Gladkov return get_tree_nodev(fc, proc_fill_super);
22797412950SVasiliy Kulikov }
22807543f5cSPavel Emelyanov
proc_fs_context_free(struct fs_context * fc)22966f592e2SDavid Howells static void proc_fs_context_free(struct fs_context *fc)
23066f592e2SDavid Howells {
23166f592e2SDavid Howells struct proc_fs_context *ctx = fc->fs_private;
23266f592e2SDavid Howells
23366f592e2SDavid Howells put_pid_ns(ctx->pid_ns);
23466f592e2SDavid Howells kfree(ctx);
23566f592e2SDavid Howells }
23666f592e2SDavid Howells
23766f592e2SDavid Howells static const struct fs_context_operations proc_fs_context_ops = {
23866f592e2SDavid Howells .free = proc_fs_context_free,
23966f592e2SDavid Howells .parse_param = proc_parse_param,
24066f592e2SDavid Howells .get_tree = proc_get_tree,
24166f592e2SDavid Howells .reconfigure = proc_reconfigure,
24266f592e2SDavid Howells };
24366f592e2SDavid Howells
proc_init_fs_context(struct fs_context * fc)24466f592e2SDavid Howells static int proc_init_fs_context(struct fs_context *fc)
24566f592e2SDavid Howells {
24666f592e2SDavid Howells struct proc_fs_context *ctx;
24766f592e2SDavid Howells
24866f592e2SDavid Howells ctx = kzalloc(sizeof(struct proc_fs_context), GFP_KERNEL);
24966f592e2SDavid Howells if (!ctx)
25066f592e2SDavid Howells return -ENOMEM;
25166f592e2SDavid Howells
25266f592e2SDavid Howells ctx->pid_ns = get_pid_ns(task_active_pid_ns(current));
25346cf047aSAl Viro put_user_ns(fc->user_ns);
25446cf047aSAl Viro fc->user_ns = get_user_ns(ctx->pid_ns->user_ns);
25566f592e2SDavid Howells fc->fs_private = ctx;
25666f592e2SDavid Howells fc->ops = &proc_fs_context_ops;
25766f592e2SDavid Howells return 0;
25807543f5cSPavel Emelyanov }
25907543f5cSPavel Emelyanov
proc_kill_sb(struct super_block * sb)26007543f5cSPavel Emelyanov static void proc_kill_sb(struct super_block *sb)
26107543f5cSPavel Emelyanov {
262fa10fed3SAlexey Gladkov struct proc_fs_info *fs_info = proc_sb_info(sb);
26307543f5cSPavel Emelyanov
264058f2e4dSAlexey Gladkov if (!fs_info) {
265058f2e4dSAlexey Gladkov kill_anon_super(sb);
266058f2e4dSAlexey Gladkov return;
267058f2e4dSAlexey Gladkov }
268fa10fed3SAlexey Gladkov
269058f2e4dSAlexey Gladkov dput(fs_info->proc_self);
270fa10fed3SAlexey Gladkov dput(fs_info->proc_thread_self);
271fa10fed3SAlexey Gladkov
27207543f5cSPavel Emelyanov kill_anon_super(sb);
273fa10fed3SAlexey Gladkov put_pid_ns(fs_info->pid_ns);
274fa10fed3SAlexey Gladkov kfree(fs_info);
2751da177e4SLinus Torvalds }
2761da177e4SLinus Torvalds
277c2319540SAlexey Dobriyan static struct file_system_type proc_fs_type = {
2781da177e4SLinus Torvalds .name = "proc",
27966f592e2SDavid Howells .init_fs_context = proc_init_fs_context,
280d7167b14SAl Viro .parameters = proc_fs_parameters,
28107543f5cSPavel Emelyanov .kill_sb = proc_kill_sb,
2820b3b094aSJan Kara .fs_flags = FS_USERNS_MOUNT | FS_DISALLOW_NOTIFY_PERM,
2831da177e4SLinus Torvalds };
2841da177e4SLinus Torvalds
proc_root_init(void)2851da177e4SLinus Torvalds void __init proc_root_init(void)
2861da177e4SLinus Torvalds {
287195b8cf0SAlexey Dobriyan proc_init_kmemcache();
2881270dd8dSAlexey Dobriyan set_proc_pid_nlink();
289e656d8a6SEric W. Biederman proc_self_init();
2900097875bSEric W. Biederman proc_thread_self_init();
291155134feSLinus Torvalds proc_symlink("mounts", NULL, "self/mounts");
292457c4cbcSEric W. Biederman
293457c4cbcSEric W. Biederman proc_net_init();
29436a5aeb8SAlexey Dobriyan proc_mkdir("fs", NULL);
295928b4d8cSAlexey Dobriyan proc_mkdir("driver", NULL);
296eb6d38d5SEric W. Biederman proc_create_mount_point("fs/nfsd"); /* somewhere for the nfsd filesystem to be mounted */
2971da177e4SLinus Torvalds #if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE)
2981da177e4SLinus Torvalds /* just give it a mountpoint */
299eb6d38d5SEric W. Biederman proc_create_mount_point("openprom");
3001da177e4SLinus Torvalds #endif
3011da177e4SLinus Torvalds proc_tty_init();
3029c37066dSAlexey Dobriyan proc_mkdir("bus", NULL);
30377b14db5SEric W. Biederman proc_sys_init();
3041539d584SAlexey Dobriyan
305ed8fb78dSAlexey Dobriyan /*
306ed8fb78dSAlexey Dobriyan * Last things last. It is not like userspace processes eager
307ed8fb78dSAlexey Dobriyan * to open /proc files exist at this point but register last
308ed8fb78dSAlexey Dobriyan * anyway.
309ed8fb78dSAlexey Dobriyan */
3101539d584SAlexey Dobriyan register_filesystem(&proc_fs_type);
3111da177e4SLinus Torvalds }
3121da177e4SLinus Torvalds
proc_root_getattr(struct mnt_idmap * idmap,const struct path * path,struct kstat * stat,u32 request_mask,unsigned int query_flags)313b74d24f7SChristian Brauner static int proc_root_getattr(struct mnt_idmap *idmap,
314549c7297SChristian Brauner const struct path *path, struct kstat *stat,
315a528d35eSDavid Howells u32 request_mask, unsigned int query_flags)
31676b6159bSAl Viro {
317*0d72b928SJeff Layton generic_fillattr(&nop_mnt_idmap, request_mask, d_inode(path->dentry),
318*0d72b928SJeff Layton stat);
31976b6159bSAl Viro stat->nlink = proc_root.nlink + nr_processes();
32076b6159bSAl Viro return 0;
32176b6159bSAl Viro }
32276b6159bSAl Viro
proc_root_lookup(struct inode * dir,struct dentry * dentry,unsigned int flags)32300cd8dd3SAl Viro static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, unsigned int flags)
3241da177e4SLinus Torvalds {
325867aaccfSZhikang Zhang if (!proc_pid_lookup(dentry, flags))
3261da177e4SLinus Torvalds return NULL;
3271da177e4SLinus Torvalds
328335eb531SAlexey Dobriyan return proc_lookup(dir, dentry, flags);
3291da177e4SLinus Torvalds }
3301da177e4SLinus Torvalds
proc_root_readdir(struct file * file,struct dir_context * ctx)331f0c3b509SAl Viro static int proc_root_readdir(struct file *file, struct dir_context *ctx)
3321da177e4SLinus Torvalds {
333f0c3b509SAl Viro if (ctx->pos < FIRST_PROCESS_ENTRY) {
33494fc5d9dSRichard Genoud int error = proc_readdir(file, ctx);
33594fc5d9dSRichard Genoud if (unlikely(error <= 0))
33694fc5d9dSRichard Genoud return error;
337f0c3b509SAl Viro ctx->pos = FIRST_PROCESS_ENTRY;
3381da177e4SLinus Torvalds }
3391da177e4SLinus Torvalds
340f0c3b509SAl Viro return proc_pid_readdir(file, ctx);
3411da177e4SLinus Torvalds }
3421da177e4SLinus Torvalds
3431da177e4SLinus Torvalds /*
3441da177e4SLinus Torvalds * The root /proc directory is special, as it has the
3451da177e4SLinus Torvalds * <pid> directories. Thus we don't use the generic
3461da177e4SLinus Torvalds * directory handling functions for that..
3471da177e4SLinus Torvalds */
34800977a59SArjan van de Ven static const struct file_operations proc_root_operations = {
3491da177e4SLinus Torvalds .read = generic_read_dir,
350f50752eaSAl Viro .iterate_shared = proc_root_readdir,
351f50752eaSAl Viro .llseek = generic_file_llseek,
3521da177e4SLinus Torvalds };
3531da177e4SLinus Torvalds
3541da177e4SLinus Torvalds /*
3551da177e4SLinus Torvalds * proc root can do almost nothing..
3561da177e4SLinus Torvalds */
357c5ef1c42SArjan van de Ven static const struct inode_operations proc_root_inode_operations = {
3581da177e4SLinus Torvalds .lookup = proc_root_lookup,
35976b6159bSAl Viro .getattr = proc_root_getattr,
3601da177e4SLinus Torvalds };
3611da177e4SLinus Torvalds
3621da177e4SLinus Torvalds /*
3631da177e4SLinus Torvalds * This is the root "inode" in the /proc tree..
3641da177e4SLinus Torvalds */
3651da177e4SLinus Torvalds struct proc_dir_entry proc_root = {
3661da177e4SLinus Torvalds .low_ino = PROC_ROOT_INO,
3671da177e4SLinus Torvalds .namelen = 5,
3681da177e4SLinus Torvalds .mode = S_IFDIR | S_IRUGO | S_IXUGO,
3691da177e4SLinus Torvalds .nlink = 2,
3709cdd83e3SAlexey Dobriyan .refcnt = REFCOUNT_INIT(1),
3711da177e4SLinus Torvalds .proc_iops = &proc_root_inode_operations,
372d56c0d45SAlexey Dobriyan .proc_dir_ops = &proc_root_operations,
3731da177e4SLinus Torvalds .parent = &proc_root,
3744f113437SAlexey Dobriyan .subdir = RB_ROOT,
37524074a35SDavid Howells .name = "/proc",
3761da177e4SLinus Torvalds };
377