Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

proc: add option to mount only a pids subset

This allows to hide all files and directories in the procfs that are not
related to tasks.

Signed-off-by: Alexey Gladkov <gladkov.alexey@gmail.com>
Reviewed-by: Alexey Dobriyan <adobriyan@gmail.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>

authored by

Alexey Gladkov and committed by
Eric W. Biederman
6814ef2d 24a71ce5

+55
+9
fs/proc/generic.c
··· 269 269 struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry, 270 270 unsigned int flags) 271 271 { 272 + struct proc_fs_info *fs_info = proc_sb_info(dir->i_sb); 273 + 274 + if (fs_info->pidonly == PROC_PIDONLY_ON) 275 + return ERR_PTR(-ENOENT); 276 + 272 277 return proc_lookup_de(dir, dentry, PDE(dir)); 273 278 } 274 279 ··· 330 325 int proc_readdir(struct file *file, struct dir_context *ctx) 331 326 { 332 327 struct inode *inode = file_inode(file); 328 + struct proc_fs_info *fs_info = proc_sb_info(inode->i_sb); 329 + 330 + if (fs_info->pidonly == PROC_PIDONLY_ON) 331 + return 1; 333 332 334 333 return proc_readdir_de(file, ctx, PDE(inode)); 335 334 }
+6
fs/proc/inode.c
··· 173 173 seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, fs_info->pid_gid)); 174 174 if (fs_info->hide_pid != HIDEPID_OFF) 175 175 seq_printf(seq, ",hidepid=%u", fs_info->hide_pid); 176 + if (fs_info->pidonly != PROC_PIDONLY_OFF) 177 + seq_printf(seq, ",subset=pid"); 176 178 177 179 return 0; 178 180 } ··· 465 463 466 464 static int proc_reg_open(struct inode *inode, struct file *file) 467 465 { 466 + struct proc_fs_info *fs_info = proc_sb_info(inode->i_sb); 468 467 struct proc_dir_entry *pde = PDE(inode); 469 468 int rv = 0; 470 469 typeof_member(struct proc_ops, proc_open) open; ··· 478 475 rv = open(inode, file); 479 476 return rv; 480 477 } 478 + 479 + if (fs_info->pidonly == PROC_PIDONLY_ON) 480 + return -ENOENT; 481 481 482 482 /* 483 483 * Ensure that
+33
fs/proc/root.c
··· 34 34 unsigned int mask; 35 35 int hidepid; 36 36 int gid; 37 + int pidonly; 37 38 }; 38 39 39 40 enum proc_param { 40 41 Opt_gid, 41 42 Opt_hidepid, 43 + Opt_subset, 42 44 }; 43 45 44 46 static const struct fs_parameter_spec proc_fs_parameters[] = { 45 47 fsparam_u32("gid", Opt_gid), 46 48 fsparam_u32("hidepid", Opt_hidepid), 49 + fsparam_string("subset", Opt_subset), 47 50 {} 48 51 }; 49 52 ··· 56 53 value == HIDEPID_NO_ACCESS || 57 54 value == HIDEPID_INVISIBLE || 58 55 value == HIDEPID_NOT_PTRACEABLE); 56 + } 57 + 58 + static int proc_parse_subset_param(struct fs_context *fc, char *value) 59 + { 60 + struct proc_fs_context *ctx = fc->fs_private; 61 + 62 + while (value) { 63 + char *ptr = strchr(value, ','); 64 + 65 + if (ptr != NULL) 66 + *ptr++ = '\0'; 67 + 68 + if (*value != '\0') { 69 + if (!strcmp(value, "pid")) { 70 + ctx->pidonly = PROC_PIDONLY_ON; 71 + } else { 72 + return invalf(fc, "proc: unsupported subset option - %s\n", value); 73 + } 74 + } 75 + value = ptr; 76 + } 77 + 78 + return 0; 59 79 } 60 80 61 81 static int proc_parse_param(struct fs_context *fc, struct fs_parameter *param) ··· 102 76 ctx->hidepid = result.uint_32; 103 77 break; 104 78 79 + case Opt_subset: 80 + if (proc_parse_subset_param(fc, param->string) < 0) 81 + return -EINVAL; 82 + break; 83 + 105 84 default: 106 85 return -EINVAL; 107 86 } ··· 125 94 fs_info->pid_gid = make_kgid(user_ns, ctx->gid); 126 95 if (ctx->mask & (1 << Opt_hidepid)) 127 96 fs_info->hide_pid = ctx->hidepid; 97 + if (ctx->mask & (1 << Opt_subset)) 98 + fs_info->pidonly = ctx->pidonly; 128 99 } 129 100 130 101 static int proc_fill_super(struct super_block *s, struct fs_context *fc)
+7
include/linux/proc_fs.h
··· 50 50 HIDEPID_NOT_PTRACEABLE = 4, /* Limit pids to only ptraceable pids */ 51 51 }; 52 52 53 + /* definitions for proc mount option pidonly */ 54 + enum { 55 + PROC_PIDONLY_OFF = 0, 56 + PROC_PIDONLY_ON = 1, 57 + }; 58 + 53 59 struct proc_fs_info { 54 60 struct pid_namespace *pid_ns; 55 61 struct dentry *proc_self; /* For /proc/self */ 56 62 struct dentry *proc_thread_self; /* For /proc/thread-self */ 57 63 kgid_t pid_gid; 58 64 int hide_pid; 65 + int pidonly; 59 66 }; 60 67 61 68 static inline struct proc_fs_info *proc_sb_info(struct super_block *sb)