Skip to content

Commit 6814ef2

Browse files
legionusebiederm
authored andcommitted
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 <[email protected]> Reviewed-by: Alexey Dobriyan <[email protected]> Reviewed-by: Kees Cook <[email protected]> Signed-off-by: Eric W. Biederman <[email protected]>
1 parent 24a71ce commit 6814ef2

File tree

4 files changed

+55
-0
lines changed

4 files changed

+55
-0
lines changed

fs/proc/generic.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,11 @@ struct dentry *proc_lookup_de(struct inode *dir, struct dentry *dentry,
269269
struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry,
270270
unsigned int flags)
271271
{
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+
272277
return proc_lookup_de(dir, dentry, PDE(dir));
273278
}
274279

@@ -325,6 +330,10 @@ int proc_readdir_de(struct file *file, struct dir_context *ctx,
325330
int proc_readdir(struct file *file, struct dir_context *ctx)
326331
{
327332
struct inode *inode = file_inode(file);
333+
struct proc_fs_info *fs_info = proc_sb_info(inode->i_sb);
334+
335+
if (fs_info->pidonly == PROC_PIDONLY_ON)
336+
return 1;
328337

329338
return proc_readdir_de(file, ctx, PDE(inode));
330339
}

fs/proc/inode.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@ static int proc_show_options(struct seq_file *seq, struct dentry *root)
173173
seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, fs_info->pid_gid));
174174
if (fs_info->hide_pid != HIDEPID_OFF)
175175
seq_printf(seq, ",hidepid=%u", fs_info->hide_pid);
176+
if (fs_info->pidonly != PROC_PIDONLY_OFF)
177+
seq_printf(seq, ",subset=pid");
176178

177179
return 0;
178180
}
@@ -463,6 +465,7 @@ proc_reg_get_unmapped_area(struct file *file, unsigned long orig_addr,
463465

464466
static int proc_reg_open(struct inode *inode, struct file *file)
465467
{
468+
struct proc_fs_info *fs_info = proc_sb_info(inode->i_sb);
466469
struct proc_dir_entry *pde = PDE(inode);
467470
int rv = 0;
468471
typeof_member(struct proc_ops, proc_open) open;
@@ -476,6 +479,9 @@ static int proc_reg_open(struct inode *inode, struct file *file)
476479
return rv;
477480
}
478481

482+
if (fs_info->pidonly == PROC_PIDONLY_ON)
483+
return -ENOENT;
484+
479485
/*
480486
* Ensure that
481487
* 1) PDE's ->release hook will be called no matter what

fs/proc/root.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,19 @@ struct proc_fs_context {
3434
unsigned int mask;
3535
int hidepid;
3636
int gid;
37+
int pidonly;
3738
};
3839

3940
enum proc_param {
4041
Opt_gid,
4142
Opt_hidepid,
43+
Opt_subset,
4244
};
4345

4446
static const struct fs_parameter_spec proc_fs_parameters[] = {
4547
fsparam_u32("gid", Opt_gid),
4648
fsparam_u32("hidepid", Opt_hidepid),
49+
fsparam_string("subset", Opt_subset),
4750
{}
4851
};
4952

@@ -55,6 +58,29 @@ static inline int valid_hidepid(unsigned int value)
5558
value == HIDEPID_NOT_PTRACEABLE);
5659
}
5760

61+
static int proc_parse_subset_param(struct fs_context *fc, char *value)
62+
{
63+
struct proc_fs_context *ctx = fc->fs_private;
64+
65+
while (value) {
66+
char *ptr = strchr(value, ',');
67+
68+
if (ptr != NULL)
69+
*ptr++ = '\0';
70+
71+
if (*value != '\0') {
72+
if (!strcmp(value, "pid")) {
73+
ctx->pidonly = PROC_PIDONLY_ON;
74+
} else {
75+
return invalf(fc, "proc: unsupported subset option - %s\n", value);
76+
}
77+
}
78+
value = ptr;
79+
}
80+
81+
return 0;
82+
}
83+
5884
static int proc_parse_param(struct fs_context *fc, struct fs_parameter *param)
5985
{
6086
struct proc_fs_context *ctx = fc->fs_private;
@@ -76,6 +102,11 @@ static int proc_parse_param(struct fs_context *fc, struct fs_parameter *param)
76102
ctx->hidepid = result.uint_32;
77103
break;
78104

105+
case Opt_subset:
106+
if (proc_parse_subset_param(fc, param->string) < 0)
107+
return -EINVAL;
108+
break;
109+
79110
default:
80111
return -EINVAL;
81112
}
@@ -94,6 +125,8 @@ static void proc_apply_options(struct proc_fs_info *fs_info,
94125
fs_info->pid_gid = make_kgid(user_ns, ctx->gid);
95126
if (ctx->mask & (1 << Opt_hidepid))
96127
fs_info->hide_pid = ctx->hidepid;
128+
if (ctx->mask & (1 << Opt_subset))
129+
fs_info->pidonly = ctx->pidonly;
97130
}
98131

99132
static int proc_fill_super(struct super_block *s, struct fs_context *fc)

include/linux/proc_fs.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,19 @@ enum {
5050
HIDEPID_NOT_PTRACEABLE = 4, /* Limit pids to only ptraceable pids */
5151
};
5252

53+
/* definitions for proc mount option pidonly */
54+
enum {
55+
PROC_PIDONLY_OFF = 0,
56+
PROC_PIDONLY_ON = 1,
57+
};
58+
5359
struct proc_fs_info {
5460
struct pid_namespace *pid_ns;
5561
struct dentry *proc_self; /* For /proc/self */
5662
struct dentry *proc_thread_self; /* For /proc/thread-self */
5763
kgid_t pid_gid;
5864
int hide_pid;
65+
int pidonly;
5966
};
6067

6168
static inline struct proc_fs_info *proc_sb_info(struct super_block *sb)

0 commit comments

Comments
 (0)