Skip to content

Commit 0fb5ce6

Browse files
committed
proc: modernize proc to support multiple private instances
Alexey Gladkov <[email protected]> writes: Procfs modernization: --------------------- Historically procfs was always tied to pid namespaces, during pid namespace creation we internally create a procfs mount for it. However, this has the effect that all new procfs mounts are just a mirror of the internal one, any change, any mount option update, any new future introduction will propagate to all other procfs mounts that are in the same pid namespace. This may have solved several use cases in that time. However today we face new requirements, and making procfs able to support new private instances inside same pid namespace seems a major point. If we want to to introduce new features and security mechanisms we have to make sure first that we do not break existing usecases. Supporting private procfs instances will allow to support new features and behaviour without propagating it to all other procfs mounts. Today procfs is more of a burden especially to some Embedded, IoT, sandbox, container use cases. In user space we are over-mounting null or inaccessible files on top to hide files and information. If we want to hide pids we have to create PID namespaces otherwise mount options propagate to all other proc mounts, changing a mount option value in one mount will propagate to all other proc mounts. If we want to introduce new features, then they will propagate to all other mounts too, resulting either maybe new useful functionality or maybe breaking stuff. We have also to note that userspace should not workaround procfs, the kernel should just provide a sane simple interface. In this regard several developers and maintainers pointed out that there are problems with procfs and it has to be modernized: "Here's another one: split up and modernize /proc." by Andy Lutomirski [1] Discussion about kernel pointer leaks: "And yes, as Kees and Daniel mentioned, it's definitely not just dmesg. In fact, the primary things tend to be /proc and /sys, not dmesg itself." By Linus Torvalds [2] Lot of other areas in the kernel and filesystems have been updated to be able to support private instances, devpts is one major example [3]. Which will be used for: 1) Embedded systems and IoT: usually we have one supervisor for apps, we have some lightweight sandbox support, however if we create pid namespaces we have to manage all the processes inside too, where our goal is to be able to run a bunch of apps each one inside its own mount namespace, maybe use network namespaces for vlans setups, but right now we only want mount namespaces, without all the other complexity. We want procfs to behave more like a real file system, and block access to inodes that belong to other users. The 'hidepid=' will not work since it is a shared mount option. 2) Containers, sandboxes and Private instances of file systems - devpts case Historically, lot of file systems inside Linux kernel view when instantiated were just a mirror of an already created and mounted filesystem. This was the case of devpts filesystem, it seems at that time the requirements were to optimize things and reuse the same memory, etc. This design used to work but not anymore with today's containers, IoT, hostile environments and all the privacy challenges that Linux faces. In that regards, devpts was updated so that each new mounts is a total independent file system by the following patches: "devpts: Make each mount of devpts an independent filesystem" by Eric W. Biederman [3] [4] 3) Linux Security Modules have multiple ptrace paths inside some subsystems, however inside procfs, the implementation does not guarantee that the ptrace() check which triggers the security_ptrace_check() hook will always run. We have the 'hidepid' mount option that can be used to force the ptrace_may_access() check inside has_pid_permissions() to run. The problem is that 'hidepid' is per pid namespace and not attached to the mount point, any remount or modification of 'hidepid' will propagate to all other procfs mounts. This also does not allow to support Yama LSM easily in desktop and user sessions. Yama ptrace scope which restricts ptrace and some other syscalls to be allowed only on inferiors, can be updated to have a per-task context, where the context will be inherited during fork(), clone() and preserved across execve(). If we support multiple private procfs instances, then we may force the ptrace_may_access() on /proc/<pids>/ to always run inside that new procfs instances. This will allow to specifiy on user sessions if we should populate procfs with pids that the user can ptrace or not. By using Yama ptrace scope, some restricted users will only be able to see inferiors inside /proc, they won't even be able to see their other processes. Some software like Chromium, Firefox's crash handler, Wine and others are already using Yama to restrict which processes can be ptracable. With this change this will give the possibility to restrict /proc/<pids>/ but more importantly this will give desktop users a generic and usuable way to specifiy which users should see all processes and which user can not. Side notes: * This covers the lack of seccomp where it is not able to parse arguments, it is easy to install a seccomp filter on direct syscalls that operate on pids, however /proc/<pid>/ is a Linux ABI using filesystem syscalls. With this change all LSMs should be able to analyze open/read/write/close... on /proc/<pid>/ 4) This will allow to implement new features either in kernel or userspace without having to worry about procfs. In containers, sandboxes, etc we have workarounds to hide some /proc inodes, this should be supported natively without doing extra complex work, the kernel should be able to support sane options that work with today and future Linux use cases. 5) Creation of new superblock with all procfs options for each procfs mount will fix the ignoring of mount options. The problem is that the second mount of procfs in the same pid namespace ignores the mount options. The mount options are ignored without error until procfs is remounted. Before: proc /proc proc rw,relatime,hidepid=2 0 0 mount("proc", "/tmp/proc", "proc", 0, "hidepid=1") = 0 +++ exited with 0 +++ proc /proc proc rw,relatime,hidepid=2 0 0 proc /tmp/proc proc rw,relatime,hidepid=2 0 0 proc /proc proc rw,relatime,hidepid=1 0 0 proc /tmp/proc proc rw,relatime,hidepid=1 0 0 After: proc /proc proc rw,relatime,hidepid=ptraceable 0 0 proc /proc proc rw,relatime,hidepid=ptraceable 0 0 proc /tmp/proc proc rw,relatime,hidepid=invisible 0 0 Introduced changes: ------------------- Each mount of procfs creates a separate procfs instance with its own mount options. This series adds few new mount options: * New 'hidepid=ptraceable' or 'hidepid=4' mount option to show only ptraceable processes in the procfs. This allows to support lightweight sandboxes in Embedded Linux, also solves the case for LSM where now with this mount option, we make sure that they have a ptrace path in procfs. * 'subset=pid' that allows to hide non-pid inodes from procfs. It can be used in containers and sandboxes, as these are already trying to hide and block access to procfs inodes anyway. ChangeLog: ---------- * Rebase on top of v5.7-rc1. * Fix a resource leak if proc is not mounted or if proc is simply reconfigured. * Add few selftests. * After a discussion with Eric W. Biederman, the numerical values for hidepid parameter have been removed from uapi. * Remove proc_self and proc_thread_self from the pid_namespace struct. * I took into account the comment of Kees Cook. * Update Reviewed-by tags. * 'subset=pidfs' renamed to 'subset=pid' as suggested by Alexey Dobriyan. * Include Reviewed-by tags. * Rebase on top of Eric W. Biederman's procfs changes. * Add human readable values of 'hidepid' as suggested by Andy Lutomirski. * Started using RCU lock to clean dcache entries as suggested by Linus Torvalds. * 'pidonly=1' renamed to 'subset=pidfs' as suggested by Alexey Dobriyan. * HIDEPID_* moved to uapi/ as they are user interface to mount(). Suggested-by Alexey Dobriyan <[email protected]> * 'hidepid=' and 'gid=' mount options are moved from pid namespace to superblock. * 'newinstance' mount option removed as suggested by Eric W. Biederman. Mount of procfs always creates a new instance. * 'limit_pids' renamed to 'hidepid=3'. * I took into account the comment of Linus Torvalds [7]. * Documentation added. * Fixed a bug that caused a problem with the Fedora boot. * The 'pidonly' option is visible among the mount options. * Renamed mount options to 'newinstance' and 'pids=' Suggested-by: Andy Lutomirski <[email protected]> * Fixed order of commit, Suggested-by: Andy Lutomirski <[email protected]> * Many bug fixes. * Removed 'unshared' mount option and replaced it with 'limit_pids' which is attached to the current procfs mount. Suggested-by Andy Lutomirski <[email protected]> * Do not fill dcache with pid entries that we can not ptrace. * Many bug fixes. References: ----------- [1] https://lists.linuxfoundation.org/pipermail/ksummit-discuss/2017-January/004215.html [2] http://www.openwall.com/lists/kernel-hardening/2017/10/05/5 [3] https://lwn.net/Articles/689539/ [4] http://lxr.free-electrons.com/source/Documentation/filesystems/devpts.txt?v=3.14 [5] https://lkml.org/lkml/2017/5/2/407 [6] https://lkml.org/lkml/2017/5/3/357 [7] https://lkml.org/lkml/2018/5/11/505 Alexey Gladkov (7): proc: rename struct proc_fs_info to proc_fs_opts proc: allow to mount many instances of proc in one pid namespace proc: instantiate only pids that we can ptrace on 'hidepid=4' mount option proc: add option to mount only a pids subset docs: proc: add documentation for "hidepid=4" and "subset=pid" options and new mount behavior proc: use human-readable values for hidepid proc: use named enums for better readability Documentation/filesystems/proc.rst | 92 +++++++++--- fs/proc/base.c | 48 +++++-- fs/proc/generic.c | 9 ++ fs/proc/inode.c | 30 +++- fs/proc/root.c | 131 +++++++++++++----- fs/proc/self.c | 6 +- fs/proc/thread_self.c | 6 +- fs/proc_namespace.c | 14 +- include/linux/pid_namespace.h | 12 -- include/linux/proc_fs.h | 30 +++- tools/testing/selftests/proc/.gitignore | 2 + tools/testing/selftests/proc/Makefile | 2 + .../selftests/proc/proc-fsconfig-hidepid.c | 50 +++++++ .../selftests/proc/proc-multiple-procfs.c | 48 +++++++ 14 files changed, 384 insertions(+), 96 deletions(-) create mode 100644 tools/testing/selftests/proc/proc-fsconfig-hidepid.c create mode 100644 tools/testing/selftests/proc/proc-multiple-procfs.c Link: https://lore.kernel.org/lkml/[email protected]/ Signed-off-by: "Eric W. Biederman" <[email protected]>
2 parents c59f415 + e61bb8b commit 0fb5ce6

File tree

14 files changed

+384
-96
lines changed

14 files changed

+384
-96
lines changed

Documentation/filesystems/proc.rst

Lines changed: 73 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ fixes/update part 1.1 Stefani Seibold <[email protected]> June 9 2009
5151
4 Configuring procfs
5252
4.1 Mount options
5353
54+
5 Filesystem behavior
55+
5456
Preface
5557
=======
5658

@@ -2142,28 +2144,80 @@ The following mount options are supported:
21422144
========= ========================================================
21432145
hidepid= Set /proc/<pid>/ access mode.
21442146
gid= Set the group authorized to learn processes information.
2147+
subset= Show only the specified subset of procfs.
21452148
========= ========================================================
21462149

2147-
hidepid=0 means classic mode - everybody may access all /proc/<pid>/ directories
2148-
(default).
2149-
2150-
hidepid=1 means users may not access any /proc/<pid>/ directories but their
2151-
own. Sensitive files like cmdline, sched*, status are now protected against
2152-
other users. This makes it impossible to learn whether any user runs
2153-
specific program (given the program doesn't reveal itself by its behaviour).
2154-
As an additional bonus, as /proc/<pid>/cmdline is unaccessible for other users,
2155-
poorly written programs passing sensitive information via program arguments are
2156-
now protected against local eavesdroppers.
2157-
2158-
hidepid=2 means hidepid=1 plus all /proc/<pid>/ will be fully invisible to other
2159-
users. It doesn't mean that it hides a fact whether a process with a specific
2160-
pid value exists (it can be learned by other means, e.g. by "kill -0 $PID"),
2161-
but it hides process' uid and gid, which may be learned by stat()'ing
2162-
/proc/<pid>/ otherwise. It greatly complicates an intruder's task of gathering
2163-
information about running processes, whether some daemon runs with elevated
2164-
privileges, whether other user runs some sensitive program, whether other users
2165-
run any program at all, etc.
2150+
hidepid=off or hidepid=0 means classic mode - everybody may access all
2151+
/proc/<pid>/ directories (default).
2152+
2153+
hidepid=noaccess or hidepid=1 means users may not access any /proc/<pid>/
2154+
directories but their own. Sensitive files like cmdline, sched*, status are now
2155+
protected against other users. This makes it impossible to learn whether any
2156+
user runs specific program (given the program doesn't reveal itself by its
2157+
behaviour). As an additional bonus, as /proc/<pid>/cmdline is unaccessible for
2158+
other users, poorly written programs passing sensitive information via program
2159+
arguments are now protected against local eavesdroppers.
2160+
2161+
hidepid=invisible or hidepid=2 means hidepid=1 plus all /proc/<pid>/ will be
2162+
fully invisible to other users. It doesn't mean that it hides a fact whether a
2163+
process with a specific pid value exists (it can be learned by other means, e.g.
2164+
by "kill -0 $PID"), but it hides process' uid and gid, which may be learned by
2165+
stat()'ing /proc/<pid>/ otherwise. It greatly complicates an intruder's task of
2166+
gathering information about running processes, whether some daemon runs with
2167+
elevated privileges, whether other user runs some sensitive program, whether
2168+
other users run any program at all, etc.
2169+
2170+
hidepid=ptraceable or hidepid=4 means that procfs should only contain
2171+
/proc/<pid>/ directories that the caller can ptrace.
21662172

21672173
gid= defines a group authorized to learn processes information otherwise
21682174
prohibited by hidepid=. If you use some daemon like identd which needs to learn
21692175
information about processes information, just add identd to this group.
2176+
2177+
subset=pid hides all top level files and directories in the procfs that
2178+
are not related to tasks.
2179+
2180+
5 Filesystem behavior
2181+
----------------------------
2182+
2183+
Originally, before the advent of pid namepsace, procfs was a global file
2184+
system. It means that there was only one procfs instance in the system.
2185+
2186+
When pid namespace was added, a separate procfs instance was mounted in
2187+
each pid namespace. So, procfs mount options are global among all
2188+
mountpoints within the same namespace.
2189+
2190+
::
2191+
2192+
# grep ^proc /proc/mounts
2193+
proc /proc proc rw,relatime,hidepid=2 0 0
2194+
2195+
# strace -e mount mount -o hidepid=1 -t proc proc /tmp/proc
2196+
mount("proc", "/tmp/proc", "proc", 0, "hidepid=1") = 0
2197+
+++ exited with 0 +++
2198+
2199+
# grep ^proc /proc/mounts
2200+
proc /proc proc rw,relatime,hidepid=2 0 0
2201+
proc /tmp/proc proc rw,relatime,hidepid=2 0 0
2202+
2203+
and only after remounting procfs mount options will change at all
2204+
mountpoints.
2205+
2206+
# mount -o remount,hidepid=1 -t proc proc /tmp/proc
2207+
2208+
# grep ^proc /proc/mounts
2209+
proc /proc proc rw,relatime,hidepid=1 0 0
2210+
proc /tmp/proc proc rw,relatime,hidepid=1 0 0
2211+
2212+
This behavior is different from the behavior of other filesystems.
2213+
2214+
The new procfs behavior is more like other filesystems. Each procfs mount
2215+
creates a new procfs instance. Mount options affect own procfs instance.
2216+
It means that it became possible to have several procfs instances
2217+
displaying tasks with different filtering options in one pid namespace.
2218+
2219+
# mount -o hidepid=invisible -t proc proc /proc
2220+
# mount -o hidepid=noaccess -t proc proc /tmp/proc
2221+
# grep ^proc /proc/mounts
2222+
proc /proc proc rw,relatime,hidepid=invisible 0 0
2223+
proc /tmp/proc proc rw,relatime,hidepid=noaccess 0 0

fs/proc/base.c

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -697,32 +697,40 @@ int proc_setattr(struct dentry *dentry, struct iattr *attr)
697697
* May current process learn task's sched/cmdline info (for hide_pid_min=1)
698698
* or euid/egid (for hide_pid_min=2)?
699699
*/
700-
static bool has_pid_permissions(struct pid_namespace *pid,
700+
static bool has_pid_permissions(struct proc_fs_info *fs_info,
701701
struct task_struct *task,
702-
int hide_pid_min)
702+
enum proc_hidepid hide_pid_min)
703703
{
704-
if (pid->hide_pid < hide_pid_min)
704+
/*
705+
* If 'hidpid' mount option is set force a ptrace check,
706+
* we indicate that we are using a filesystem syscall
707+
* by passing PTRACE_MODE_READ_FSCREDS
708+
*/
709+
if (fs_info->hide_pid == HIDEPID_NOT_PTRACEABLE)
710+
return ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS);
711+
712+
if (fs_info->hide_pid < hide_pid_min)
705713
return true;
706-
if (in_group_p(pid->pid_gid))
714+
if (in_group_p(fs_info->pid_gid))
707715
return true;
708716
return ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS);
709717
}
710718

711719

712720
static int proc_pid_permission(struct inode *inode, int mask)
713721
{
714-
struct pid_namespace *pid = proc_pid_ns(inode);
722+
struct proc_fs_info *fs_info = proc_sb_info(inode->i_sb);
715723
struct task_struct *task;
716724
bool has_perms;
717725

718726
task = get_proc_task(inode);
719727
if (!task)
720728
return -ESRCH;
721-
has_perms = has_pid_permissions(pid, task, HIDEPID_NO_ACCESS);
729+
has_perms = has_pid_permissions(fs_info, task, HIDEPID_NO_ACCESS);
722730
put_task_struct(task);
723731

724732
if (!has_perms) {
725-
if (pid->hide_pid == HIDEPID_INVISIBLE) {
733+
if (fs_info->hide_pid == HIDEPID_INVISIBLE) {
726734
/*
727735
* Let's make getdents(), stat(), and open()
728736
* consistent with each other. If a process
@@ -1897,7 +1905,7 @@ int pid_getattr(const struct path *path, struct kstat *stat,
18971905
u32 request_mask, unsigned int query_flags)
18981906
{
18991907
struct inode *inode = d_inode(path->dentry);
1900-
struct pid_namespace *pid = proc_pid_ns(inode);
1908+
struct proc_fs_info *fs_info = proc_sb_info(inode->i_sb);
19011909
struct task_struct *task;
19021910

19031911
generic_fillattr(inode, stat);
@@ -1907,7 +1915,7 @@ int pid_getattr(const struct path *path, struct kstat *stat,
19071915
rcu_read_lock();
19081916
task = pid_task(proc_pid(inode), PIDTYPE_PID);
19091917
if (task) {
1910-
if (!has_pid_permissions(pid, task, HIDEPID_INVISIBLE)) {
1918+
if (!has_pid_permissions(fs_info, task, HIDEPID_INVISIBLE)) {
19111919
rcu_read_unlock();
19121920
/*
19131921
* This doesn't prevent learning whether PID exists,
@@ -3300,14 +3308,16 @@ struct dentry *proc_pid_lookup(struct dentry *dentry, unsigned int flags)
33003308
{
33013309
struct task_struct *task;
33023310
unsigned tgid;
3311+
struct proc_fs_info *fs_info;
33033312
struct pid_namespace *ns;
33043313
struct dentry *result = ERR_PTR(-ENOENT);
33053314

33063315
tgid = name_to_int(&dentry->d_name);
33073316
if (tgid == ~0U)
33083317
goto out;
33093318

3310-
ns = dentry->d_sb->s_fs_info;
3319+
fs_info = proc_sb_info(dentry->d_sb);
3320+
ns = fs_info->pid_ns;
33113321
rcu_read_lock();
33123322
task = find_task_by_pid_ns(tgid, ns);
33133323
if (task)
@@ -3316,7 +3326,14 @@ struct dentry *proc_pid_lookup(struct dentry *dentry, unsigned int flags)
33163326
if (!task)
33173327
goto out;
33183328

3329+
/* Limit procfs to only ptraceable tasks */
3330+
if (fs_info->hide_pid == HIDEPID_NOT_PTRACEABLE) {
3331+
if (!has_pid_permissions(fs_info, task, HIDEPID_NO_ACCESS))
3332+
goto out_put_task;
3333+
}
3334+
33193335
result = proc_pid_instantiate(dentry, task, NULL);
3336+
out_put_task:
33203337
put_task_struct(task);
33213338
out:
33223339
return result;
@@ -3371,20 +3388,21 @@ static struct tgid_iter next_tgid(struct pid_namespace *ns, struct tgid_iter ite
33713388
int proc_pid_readdir(struct file *file, struct dir_context *ctx)
33723389
{
33733390
struct tgid_iter iter;
3391+
struct proc_fs_info *fs_info = proc_sb_info(file_inode(file)->i_sb);
33743392
struct pid_namespace *ns = proc_pid_ns(file_inode(file));
33753393
loff_t pos = ctx->pos;
33763394

33773395
if (pos >= PID_MAX_LIMIT + TGID_OFFSET)
33783396
return 0;
33793397

33803398
if (pos == TGID_OFFSET - 2) {
3381-
struct inode *inode = d_inode(ns->proc_self);
3399+
struct inode *inode = d_inode(fs_info->proc_self);
33823400
if (!dir_emit(ctx, "self", 4, inode->i_ino, DT_LNK))
33833401
return 0;
33843402
ctx->pos = pos = pos + 1;
33853403
}
33863404
if (pos == TGID_OFFSET - 1) {
3387-
struct inode *inode = d_inode(ns->proc_thread_self);
3405+
struct inode *inode = d_inode(fs_info->proc_thread_self);
33883406
if (!dir_emit(ctx, "thread-self", 11, inode->i_ino, DT_LNK))
33893407
return 0;
33903408
ctx->pos = pos = pos + 1;
@@ -3398,7 +3416,7 @@ int proc_pid_readdir(struct file *file, struct dir_context *ctx)
33983416
unsigned int len;
33993417

34003418
cond_resched();
3401-
if (!has_pid_permissions(ns, iter.task, HIDEPID_INVISIBLE))
3419+
if (!has_pid_permissions(fs_info, iter.task, HIDEPID_INVISIBLE))
34023420
continue;
34033421

34043422
len = snprintf(name, sizeof(name), "%u", iter.tgid);
@@ -3598,6 +3616,7 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry
35983616
struct task_struct *task;
35993617
struct task_struct *leader = get_proc_task(dir);
36003618
unsigned tid;
3619+
struct proc_fs_info *fs_info;
36013620
struct pid_namespace *ns;
36023621
struct dentry *result = ERR_PTR(-ENOENT);
36033622

@@ -3608,7 +3627,8 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry
36083627
if (tid == ~0U)
36093628
goto out;
36103629

3611-
ns = dentry->d_sb->s_fs_info;
3630+
fs_info = proc_sb_info(dentry->d_sb);
3631+
ns = fs_info->pid_ns;
36123632
rcu_read_lock();
36133633
task = find_task_by_pid_ns(tid, ns);
36143634
if (task)

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: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <linux/seq_file.h>
2525
#include <linux/slab.h>
2626
#include <linux/mount.h>
27+
#include <linux/bug.h>
2728

2829
#include <linux/uaccess.h>
2930

@@ -165,15 +166,28 @@ void proc_invalidate_siblings_dcache(struct hlist_head *inodes, spinlock_t *lock
165166
deactivate_super(old_sb);
166167
}
167168

169+
static inline const char *hidepid2str(enum proc_hidepid v)
170+
{
171+
switch (v) {
172+
case HIDEPID_OFF: return "off";
173+
case HIDEPID_NO_ACCESS: return "noaccess";
174+
case HIDEPID_INVISIBLE: return "invisible";
175+
case HIDEPID_NOT_PTRACEABLE: return "ptraceable";
176+
}
177+
WARN_ONCE(1, "bad hide_pid value: %d\n", v);
178+
return "unknown";
179+
}
180+
168181
static int proc_show_options(struct seq_file *seq, struct dentry *root)
169182
{
170-
struct super_block *sb = root->d_sb;
171-
struct pid_namespace *pid = sb->s_fs_info;
183+
struct proc_fs_info *fs_info = proc_sb_info(root->d_sb);
172184

173-
if (!gid_eq(pid->pid_gid, GLOBAL_ROOT_GID))
174-
seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, pid->pid_gid));
175-
if (pid->hide_pid != HIDEPID_OFF)
176-
seq_printf(seq, ",hidepid=%u", pid->hide_pid);
185+
if (!gid_eq(fs_info->pid_gid, GLOBAL_ROOT_GID))
186+
seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, fs_info->pid_gid));
187+
if (fs_info->hide_pid != HIDEPID_OFF)
188+
seq_printf(seq, ",hidepid=%s", hidepid2str(fs_info->hide_pid));
189+
if (fs_info->pidonly != PROC_PIDONLY_OFF)
190+
seq_printf(seq, ",subset=pid");
177191

178192
return 0;
179193
}
@@ -464,6 +478,7 @@ proc_reg_get_unmapped_area(struct file *file, unsigned long orig_addr,
464478

465479
static int proc_reg_open(struct inode *inode, struct file *file)
466480
{
481+
struct proc_fs_info *fs_info = proc_sb_info(inode->i_sb);
467482
struct proc_dir_entry *pde = PDE(inode);
468483
int rv = 0;
469484
typeof_member(struct proc_ops, proc_open) open;
@@ -477,6 +492,9 @@ static int proc_reg_open(struct inode *inode, struct file *file)
477492
return rv;
478493
}
479494

495+
if (fs_info->pidonly == PROC_PIDONLY_ON)
496+
return -ENOENT;
497+
480498
/*
481499
* Ensure that
482500
* 1) PDE's ->release hook will be called no matter what

0 commit comments

Comments
 (0)