Greetings!
Preface:
--------
This is patchset v8 to modernize procfs and make it able to support multiple
private instances per the same pid namespace.
This patchset can be applied on top of v5.4-rc7-49-g0e3f1ad80fc8
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:
# grep ^proc /proc/mounts
proc /proc proc rw,relatime,hidepid=2 0 0
# strace -e mount mount -o hidepid=1 -t proc proc /tmp/proc
mount("proc", "/tmp/proc", "proc", 0, "hidepid=1") = 0
+++ exited with 0 +++
# grep ^proc /proc/mounts
proc /proc proc rw,relatime,hidepid=2 0 0
proc /tmp/proc proc rw,relatime,hidepid=2 0 0
# mount -o remount,hidepid=1 -t proc proc /tmp/proc
# grep ^proc /proc/mounts
proc /proc proc rw,relatime,hidepid=1 0 0
proc /tmp/proc proc rw,relatime,hidepid=1 0 0
After:
# grep ^proc /proc/mounts
proc /proc proc rw,relatime,hidepid=2 0 0
# mount -o hidepid=1 -t proc proc /tmp/proc
# grep ^proc /proc/mounts
proc /proc proc rw,relatime,hidepid=2 0 0
proc /tmp/proc proc rw,relatime,hidepid=1 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=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=pidfs' 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:
----------
# v8:
* Started using RCU lock to clean dcache entries as Linus Torvalds suggested.
# v7:
* 'pidonly=1' renamed to 'subset=pidfs' as Alexey Dobriyan suggested.
* HIDEPID_* moved to uapi/ as they are user interface to mount().
Suggested-by Alexey Dobriyan [off-list ref]
# v6:
* 'hidepid=' and 'gid=' mount options are moved from pid namespace to superblock.
* 'newinstance' mount option removed as Eric W. Biederman suggested.
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.
# v5:
* Fixed a bug that caused a problem with the Fedora boot.
* The 'pidonly' option is visible among the mount options.
# v2:
* Renamed mount options to 'newinstance' and 'pids='
Suggested-by: Andy Lutomirski [off-list ref]
* Fixed order of commit, Suggested-by: Andy Lutomirski [off-list ref]
* Many bug fixes.
# v1:
* Removed 'unshared' mount option and replaced it with 'limit_pids'
which is attached to the current procfs mount.
Suggested-by Andy Lutomirski [off-list ref]
* 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 (11):
proc: Rename struct proc_fs_info to proc_fs_opts
proc: add proc_fs_info struct to store proc information
proc: move /proc/{self|thread-self} dentries to proc_fs_info
proc: move hide_pid, pid_gid from pid_namespace to proc_fs_info
proc: add helpers to set and get proc hidepid and gid mount options
proc: support mounting procfs instances inside same pid namespace
proc: flush task dcache entries from all procfs instances
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=pidfs"
options and new mount behavior
proc: Move hidepid values to uapi as they are user interface to mount
Documentation/filesystems/proc.txt | 53 +++++++++++
fs/locks.c | 6 +-
fs/proc/base.c | 66 ++++++++++----
fs/proc/generic.c | 9 ++
fs/proc/inode.c | 21 +++--
fs/proc/internal.h | 30 ++++++
fs/proc/root.c | 141 +++++++++++++++++++++++------
fs/proc/self.c | 4 +-
fs/proc/thread_self.c | 6 +-
fs/proc_namespace.c | 14 +--
include/linux/pid_namespace.h | 14 +--
include/linux/proc_fs.h | 25 ++++-
include/uapi/linux/proc_fs.h | 13 +++
13 files changed, 324 insertions(+), 78 deletions(-)
create mode 100644 include/uapi/linux/proc_fs.h
--
2.24.1
This is a preparation patch that adds proc_fs_info to be able to store
different procfs options and informations. Right now some mount options
are stored inside the pid namespace which makes it hard to change or
modernize procfs without affecting pid namespaces. Plus we do want to
treat proc as more of a real mount point and filesystem. procfs is part
of Linux API where it offers some features using filesystem syscalls and
in order to support some features where we are able to have multiple
instances of procfs, each one with its mount options inside the same pid
namespace, we have to separate these procfs instances.
This is the same feature that was also added to other Linux interfaces
like devpts in order to support containers, sandboxes, and to have
multiple instances of devpts filesystem [1].
[1] https://elixir.bootlin.com/linux/v3.4/source/Documentation/filesystems/devpts.txt
Cc: Kees Cook <redacted>
Suggested-by: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Djalal Harouni <redacted>
Signed-off-by: Alexey Gladkov <redacted>
---
fs/locks.c | 6 +++--
fs/proc/base.c | 8 +++++--
fs/proc/inode.c | 4 ++--
fs/proc/root.c | 49 +++++++++++++++++++++++++++--------------
include/linux/proc_fs.h | 11 ++++++++-
5 files changed, 54 insertions(+), 24 deletions(-)
@@ -146,7 +155,7 @@ int open_related_ns(struct ns_common *ns,/* get the associated pid namespace for a file in procfs */staticinlinestructpid_namespace*proc_pid_ns(conststructinode*inode){-returninode->i_sb->s_fs_info;+returnproc_sb_info(inode->i_sb)->pid_ns;}#endif /* _LINUX_PROC_FS_H */
This is a preparation patch that moves /proc/{self|thread-self} dentries
to be stored inside procfs fs_info struct instead of making them per pid
namespace. Since we want to support multiple procfs instances we need to
make sure that these dentries are also per-superblock instead of
per-pidns, unmounting a private procfs won't clash with other procfs
mounts.
Cc: Kees Cook <redacted>
Cc: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Djalal Harouni <redacted>
Signed-off-by: Alexey Gladkov <redacted>
---
fs/proc/base.c | 5 +++--
fs/proc/root.c | 8 ++++----
fs/proc/self.c | 4 ++--
fs/proc/thread_self.c | 6 +++---
include/linux/pid_namespace.h | 4 +---
include/linux/proc_fs.h | 2 ++
6 files changed, 15 insertions(+), 14 deletions(-)
From: Andy Lutomirski <luto@kernel.org> Date: 2020-02-10 18:23:39
On Mon, Feb 10, 2020 at 7:06 AM Alexey Gladkov [off-list ref] wrote:
This is a preparation patch that moves /proc/{self|thread-self} dentries
to be stored inside procfs fs_info struct instead of making them per pid
namespace. Since we want to support multiple procfs instances we need to
make sure that these dentries are also per-superblock instead of
per-pidns,
The changelog makes perfect sense so far...
unmounting a private procfs won't clash with other procfs
mounts.
This doesn't parse as part of the previous sentence. I'm also not
convinced that this really involves unmounting per se. Maybe just
delete these words.
On Mon, Feb 10, 2020 at 10:23:23AM -0800, Andy Lutomirski wrote:
On Mon, Feb 10, 2020 at 7:06 AM Alexey Gladkov [off-list ref] wrote:
quoted
This is a preparation patch that moves /proc/{self|thread-self} dentries
to be stored inside procfs fs_info struct instead of making them per pid
namespace. Since we want to support multiple procfs instances we need to
make sure that these dentries are also per-superblock instead of
per-pidns,
The changelog makes perfect sense so far...
quoted
unmounting a private procfs won't clash with other procfs
mounts.
This doesn't parse as part of the previous sentence. I'm also not
convinced that this really involves unmounting per se. Maybe just
delete these words.
This allows to flush dcache entries of a task on multiple procfs mounts
per pid namespace.
The RCU lock is used because the number of reads at the task exit time
is much larger than the number of procfs mounts.
Cc: Kees Cook <redacted>
Cc: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Djalal Harouni <redacted>
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Alexey Gladkov <redacted>
---
fs/proc/base.c | 20 +++++++++++++++-----
fs/proc/root.c | 27 ++++++++++++++++++++++++++-
include/linux/pid_namespace.h | 2 ++
include/linux/proc_fs.h | 2 ++
4 files changed, 45 insertions(+), 6 deletions(-)
@@ -26,6 +26,8 @@ struct pid_namespace {structpid_namespace*parent;#ifdef CONFIG_PROC_FSstructvfsmount*proc_mnt;/* Internal proc mounted during each new pidns */+spinlock_tproc_mounts_lock;+structlist_headproc_mounts;/* list of separated procfs mounts */#endif#ifdef CONFIG_BSD_PROCESS_ACCTstructfs_pin*bacct;
@@ -20,6 +20,8 @@ enum {};structproc_fs_info{+structlist_headpidns_entry;/* Node in procfs_mounts of a pidns */+structsuper_block*m_super;structpid_namespace*pid_ns;structdentry*proc_self;/* For /proc/self */structdentry*proc_thread_self;/* For /proc/thread-self */
On Mon, Feb 10, 2020 at 7:06 AM Alexey Gladkov [off-list ref] wrote:
This allows to flush dcache entries of a task on multiple procfs mounts
per pid namespace.
The RCU lock is used because the number of reads at the task exit time
is much larger than the number of procfs mounts.
Ok, this looks better to me than the previous version.
But that may be the "pee-in-the-snow" effect, and I _really_ want
others to take a good look at the whole series.
The right people seem to be cc'd, but this is pretty core, and /proc
has a tendency to cause interesting issues because of how it's
involved in a lot of areas indirectly.
Al, Oleg, Andy, Eric?
Linus
From: Al Viro <viro@zeniv.linux.org.uk> Date: 2020-02-10 19:23:16
On Mon, Feb 10, 2020 at 09:46:26AM -0800, Linus Torvalds wrote:
On Mon, Feb 10, 2020 at 7:06 AM Alexey Gladkov [off-list ref] wrote:
quoted
This allows to flush dcache entries of a task on multiple procfs mounts
per pid namespace.
The RCU lock is used because the number of reads at the task exit time
is much larger than the number of procfs mounts.
Ok, this looks better to me than the previous version.
But that may be the "pee-in-the-snow" effect, and I _really_ want
others to take a good look at the whole series.
The right people seem to be cc'd, but this is pretty core, and /proc
has a tendency to cause interesting issues because of how it's
involved in a lot of areas indirectly.
Al, Oleg, Andy, Eric?
Will check tonight (ears-deep in sorting out the old branches right now)
From: Al Viro <viro@zeniv.linux.org.uk> Date: 2020-02-11 22:46:05
On Mon, Feb 10, 2020 at 04:05:15PM +0100, Alexey Gladkov wrote:
quoted hunk
This allows to flush dcache entries of a task on multiple procfs mounts
per pid namespace.
The RCU lock is used because the number of reads at the task exit time
is much larger than the number of procfs mounts.
Cc: Kees Cook <redacted>
Cc: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Djalal Harouni <redacted>
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Alexey Gladkov <redacted>
---
fs/proc/base.c | 20 +++++++++++++++-----
fs/proc/root.c | 27 ++++++++++++++++++++++++++-
include/linux/pid_namespace.h | 2 ++
include/linux/proc_fs.h | 2 ++
4 files changed, 45 insertions(+), 6 deletions(-)
On Tue, Feb 11, 2020 at 10:45:53PM +0000, Al Viro wrote:
On Mon, Feb 10, 2020 at 04:05:15PM +0100, Alexey Gladkov wrote:
quoted
This allows to flush dcache entries of a task on multiple procfs mounts
per pid namespace.
The RCU lock is used because the number of reads at the task exit time
is much larger than the number of procfs mounts.
Cc: Kees Cook <redacted>
Cc: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Djalal Harouni <redacted>
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Alexey Gladkov <redacted>
---
fs/proc/base.c | 20 +++++++++++++++-----
fs/proc/root.c | 27 ++++++++++++++++++++++++++-
include/linux/pid_namespace.h | 2 ++
include/linux/proc_fs.h | 2 ++
4 files changed, 45 insertions(+), 6 deletions(-)
@@ -50,6 +50,8 @@ Table of Contents 4 Configuring procfs 4.1 Mount options+ 5 Filesystem behavior+ ------------------------------------------------------------------------------ Preface ------------------------------------------------------------------------------
@@ -2021,6 +2023,7 @@ The following mount options are supported: hidepid= Set /proc/<pid>/ access mode. gid= Set the group authorized to learn processes information.+ subset= Show only the specified subset of procfs. hidepid=0 means classic mode - everybody may access all /proc/<pid>/ directories (default).
@@ -2042,6 +2045,56 @@ information about running processes, whether some daemon runs with elevated privileges, whether other user runs some sensitive program, whether other users run any program at all, etc.+hidepid=4 means that procfs should only contain /proc/<pid>/ directories+that the caller can ptrace.+ gid= defines a group authorized to learn processes information otherwise prohibited by hidepid=. If you use some daemon like identd which needs to learn information about processes information, just add identd to this group.++subset=pidfs hides all top level files and directories in the procfs that+are not related to tasks.++------------------------------------------------------------------------------+5 Filesystem behavior+------------------------------------------------------------------------------++Originally, before the advent of pid namepsace, procfs was a global file+system. It means that there was only one procfs instance in the system.++When pid namespace was added, a separate procfs instance was mounted in+each pid namespace. So, procfs mount options are global among all+mountpoints within the same namespace.++# grep ^proc /proc/mounts+proc /proc proc rw,relatime,hidepid=2 0 0++# strace -e mount mount -o hidepid=1 -t proc proc /tmp/proc+mount("proc", "/tmp/proc", "proc", 0, "hidepid=1") = 0++++ exited with 0 +++++# grep ^proc /proc/mounts+proc /proc proc rw,relatime,hidepid=2 0 0+proc /tmp/proc proc rw,relatime,hidepid=2 0 0++and only after remounting procfs mount options will change at all+mountpoints.++# mount -o remount,hidepid=1 -t proc proc /tmp/proc++# grep ^proc /proc/mounts+proc /proc proc rw,relatime,hidepid=1 0 0+proc /tmp/proc proc rw,relatime,hidepid=1 0 0++This behavior is different from the behavior of other filesystems.++The new procfs behavior is more like other filesystems. Each procfs mount+creates a new procfs instance. Mount options affect own procfs instance.+It means that it became possible to have several procfs instances+displaying tasks with different filtering options in one pid namespace.++# mount -o hidepid=2 -t proc proc /proc+# mount -o hidepid=1 -t proc proc /tmp/proc+# grep ^proc /proc/mounts+proc /proc proc rw,relatime,hidepid=2 0 0+proc /tmp/proc proc rw,relatime,hidepid=1 0 0
@@ -50,6 +50,8 @@ Table of Contents 4 Configuring procfs 4.1 Mount options+ 5 Filesystem behavior+ ------------------------------------------------------------------------------ Preface ------------------------------------------------------------------------------
@@ -2021,6 +2023,7 @@ The following mount options are supported: hidepid= Set /proc/<pid>/ access mode. gid= Set the group authorized to learn processes information.+ subset= Show only the specified subset of procfs. hidepid=0 means classic mode - everybody may access all /proc/<pid>/ directories (default).
@@ -2042,6 +2045,56 @@ information about running processes, whether some daemon runs with elevated privileges, whether other user runs some sensitive program, whether other users run any program at all, etc.+hidepid=4 means that procfs should only contain /proc/<pid>/ directories+that the caller can ptrace.
I have a couple of minor nits here.
First, perhaps we could stop using magic numbers and use words.
hidepid=ptraceable is actually comprehensible, whereas hidepid=4
requires looking up what '4' means.
Second, there is PTRACE_MODE_ATTACH and PTRACE_MODE_READ. Which is it?
+
gid= defines a group authorized to learn processes information otherwise
prohibited by hidepid=. If you use some daemon like identd which needs to learn
information about processes information, just add identd to this group.
How is this better than just creating an entirely separate mount a
different hidepid and a different gid owning it? In any event,
usually gid= means that this gid is the group owner of inodes. Let's
call it something different. gid_override_hidepid might be credible.
But it's also really weird -- do different groups really see different
contents when they read a directory?
@@ -50,6 +50,8 @@ Table of Contents 4 Configuring procfs 4.1 Mount options+ 5 Filesystem behavior+ ------------------------------------------------------------------------------ Preface ------------------------------------------------------------------------------
@@ -2021,6 +2023,7 @@ The following mount options are supported: hidepid= Set /proc/<pid>/ access mode. gid= Set the group authorized to learn processes information.+ subset= Show only the specified subset of procfs. hidepid=0 means classic mode - everybody may access all /proc/<pid>/ directories (default).
@@ -2042,6 +2045,56 @@ information about running processes, whether some daemon runs with elevated privileges, whether other user runs some sensitive program, whether other users run any program at all, etc.+hidepid=4 means that procfs should only contain /proc/<pid>/ directories+that the caller can ptrace.
I have a couple of minor nits here.
First, perhaps we could stop using magic numbers and use words.
hidepid=ptraceable is actually comprehensible, whereas hidepid=4
requires looking up what '4' means.
Do you mean to add string aliases for the values?
hidepid=0 == hidepid=default
hidepid=1 == hidepid=restrict
hidepid=2 == hidepid=ownonly
hidepid=4 == hidepid=ptraceable
Something like that ?
Second, there is PTRACE_MODE_ATTACH and PTRACE_MODE_READ. Which is it?
This is PTRACE_MODE_READ.
quoted
+
gid= defines a group authorized to learn processes information otherwise
prohibited by hidepid=. If you use some daemon like identd which needs to learn
information about processes information, just add identd to this group.
How is this better than just creating an entirely separate mount a
different hidepid and a different gid owning it?
I'm not sure I understand the question. Now you cannot have two proc with
different hidepid in the same pid_namespace.
In any event,
usually gid= means that this gid is the group owner of inodes. Let's
call it something different. gid_override_hidepid might be credible.
But it's also really weird -- do different groups really see different
contents when they read a directory?
If you use hidepid=2,gid=wheel options then the user is not in the wheel
group will see only their processes and the user in the wheel group will
see whole tree. The gid= is a kind of whitelist for hidepid=1|2.
--
Rgrds, legion
@@ -7,19 +7,12 @@#include<linux/types.h>#include<linux/fs.h>+#include<uapi/linux/proc_fs.h>structproc_dir_entry;structseq_file;structseq_operations;-/* definitions for hide_pid field */-enum{-HIDEPID_OFF=0,-HIDEPID_NO_ACCESS=1,-HIDEPID_INVISIBLE=2,-HIDEPID_NOT_PTRACABLE=4,/* Limit pids to only ptracable pids */-};-/* definitions for proc mount option pidonly */enum{PROC_PIDONLY_OFF=0,
This allows to hide all files and directories in the procfs that are not
related to tasks.
Signed-off-by: Alexey Gladkov <redacted>
---
fs/proc/generic.c | 9 +++++++++
fs/proc/inode.c | 7 +++++++
fs/proc/internal.h | 10 ++++++++++
fs/proc/root.c | 36 ++++++++++++++++++++++++++++++++++++
include/linux/proc_fs.h | 7 +++++++
5 files changed, 69 insertions(+)
@@ -20,6 +20,12 @@ enum {HIDEPID_NOT_PTRACABLE=4,/* Limit pids to only ptracable pids */};+/* definitions for proc mount option pidonly */+enum{+PROC_PIDONLY_OFF=0,+PROC_PIDONLY_ON=1,+};+structproc_fs_info{structlist_headpidns_entry;/* Node in procfs_mounts of a pidns */structsuper_block*m_super;
@@ -28,6 +34,7 @@ struct proc_fs_info {structdentry*proc_thread_self;/* For /proc/thread-self */kgid_tpid_gid;inthide_pid;+intpidonly;};staticinlinestructproc_fs_info*proc_sb_info(structsuper_block*sb)
If "hidepid=4" mount option is set then do not instantiate pids that
we can not ptrace. "hidepid=4" means that procfs should only contain
pids that the caller can ptrace.
Cc: Kees Cook <redacted>
Cc: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Djalal Harouni <redacted>
Signed-off-by: Alexey Gladkov <redacted>
---
fs/proc/base.c | 15 +++++++++++++++
fs/proc/root.c | 14 +++++++++++---
include/linux/proc_fs.h | 1 +
3 files changed, 27 insertions(+), 3 deletions(-)
@@ -68,10 +77,9 @@ static int proc_parse_param(struct fs_context *fc, struct fs_parameter *param)break;caseOpt_hidepid:+if(!valid_hidepid(result.uint_32))+returninvalf(fc,"proc: unknown value of hidepid.\n");ctx->hidepid=result.uint_32;-if(ctx->hidepid<HIDEPID_OFF||-ctx->hidepid>HIDEPID_INVISIBLE)-returninvalf(fc,"proc: hidepid value must be between 0 and 2.\n");break;default:
From: Jordan Glover <hidden> Date: 2020-02-10 16:29:46
On Monday, February 10, 2020 3:05 PM, Alexey Gladkov [off-list ref] wrote:
quoted hunk
If "hidepid=4" mount option is set then do not instantiate pids that
we can not ptrace. "hidepid=4" means that procfs should only contain
pids that the caller can ptrace.
Cc: Kees Cook keescook@chromium.org
Cc: Andy Lutomirski luto@kernel.org
Signed-off-by: Djalal Harouni tixxdz@gmail.com
Signed-off-by: Alexey Gladkov gladkov.alexey@gmail.com
fs/proc/base.c | 15 +++++++++++++++
fs/proc/root.c | 14 +++++++++++---
include/linux/proc_fs.h | 1 +
3 files changed, 27 insertions(+), 3 deletions(-)
break;
case Opt_hidepid:
- if (!valid_hidepid(result.uint_32))
- return invalf(fc, "proc: unknown value of hidepid.\\n");
ctx->hidepid = result.uint_32;
- if (ctx->hidepid < HIDEPID_OFF ||
- ctx->hidepid > HIDEPID_INVISIBLE)
- return invalf(fc, "proc: hidepid value must be between 0 and 2.\\n");
break;
default:
On Mon, Feb 10, 2020 at 04:29:31PM +0000, Jordan Glover wrote:
On Monday, February 10, 2020 3:05 PM, Alexey Gladkov [off-list ref] wrote:
quoted
If "hidepid=4" mount option is set then do not instantiate pids that
we can not ptrace. "hidepid=4" means that procfs should only contain
pids that the caller can ptrace.
Cc: Kees Cook keescook@chromium.org
Cc: Andy Lutomirski luto@kernel.org
Signed-off-by: Djalal Harouni tixxdz@gmail.com
Signed-off-by: Alexey Gladkov gladkov.alexey@gmail.com
fs/proc/base.c | 15 +++++++++++++++
fs/proc/root.c | 14 +++++++++++---
include/linux/proc_fs.h | 1 +
3 files changed, 27 insertions(+), 3 deletions(-)
break;
case Opt_hidepid:
- if (!valid_hidepid(result.uint_32))
- return invalf(fc, "proc: unknown value of hidepid.\\n");
ctx->hidepid = result.uint_32;
- if (ctx->hidepid < HIDEPID_OFF ||
- ctx->hidepid > HIDEPID_INVISIBLE)
- return invalf(fc, "proc: hidepid value must be between 0 and 2.\\n");
break;
default:
Is there a reason new option is "4" instead of "3"? The order 1..2..4 may be
confusing for people.
This is just mask. For now hidepid values are mutually exclusive, but
since it moved to uapi, I thought it would be good if there was an
opportunity to combine values.
--
Rgrds, legion
This is a cleaning patch to add helpers to set and get proc mount
options instead of directly using them. This make it easy to track
what's happening and easy to update in future.
Cc: Kees Cook <redacted>
Cc: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Djalal Harouni <redacted>
Signed-off-by: Alexey Gladkov <redacted>
---
fs/proc/base.c | 6 +++---
fs/proc/inode.c | 11 +++++++----
fs/proc/internal.h | 20 ++++++++++++++++++++
fs/proc/root.c | 8 ++++----
4 files changed, 34 insertions(+), 11 deletions(-)
From: Andy Lutomirski <luto@kernel.org> Date: 2020-02-10 18:31:03
On Mon, Feb 10, 2020 at 7:06 AM Alexey Gladkov [off-list ref] wrote:
This is a cleaning patch to add helpers to set and get proc mount
options instead of directly using them. This make it easy to track
what's happening and easy to update in future.
On a cursory inspection, this looks like it obfuscates the code, and I
don't see where it does something useful later in the series. What is
this abstraction for?
--Andy
On Mon, Feb 10, 2020 at 10:30:45AM -0800, Andy Lutomirski wrote:
On Mon, Feb 10, 2020 at 7:06 AM Alexey Gladkov [off-list ref] wrote:
quoted
This is a cleaning patch to add helpers to set and get proc mount
options instead of directly using them. This make it easy to track
what's happening and easy to update in future.
On a cursory inspection, this looks like it obfuscates the code, and I
don't see where it does something useful later in the series. What is
this abstraction for?
To be honest, this part is from Djalal Harouni. For me, these wrappers
exist for a slight increase in readability.
I will not cry if you tell me to remove them :)
--
Rgrds, legion
This patch allows to have multiple procfs instances inside the
same pid namespace. The aim here is lightweight sandboxes, and to allow
that we have to modernize procfs internals.
1) The main aim of this work is to have on embedded systems one
supervisor for apps. Right now we have some lightweight sandbox support,
however if we create pid namespacess we have to manages 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 without being able to
notice each other. We only want to use mount namespaces, and we want
procfs to behave more like a real mount point.
2) 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 users 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 LSMs should be able to analyze
open/read/write/close...
In the new patchset version I removed the 'newinstance' option
as Eric W. Biederman suggested.
Cc: Kees Cook <redacted>
Cc: "Eric W. Biederman" <redacted>
Signed-off-by: Alexey Gladkov <redacted>
---
fs/proc/root.c | 41 ++++++++++++++++++-----------------------
1 file changed, 18 insertions(+), 23 deletions(-)
@@ -108,7 +110,7 @@ static int proc_fill_super(struct super_block *s, struct fs_context *fc)structinode*root_inode;intret;-proc_apply_options(s,fc,pid_ns,current_user_ns());+proc_apply_options(ctx->fs_info,fc,pid_ns,current_user_ns());/* User space would break if executables or devices appear on proc */s->s_iflags|=SB_I_USERNS_VISIBLE|SB_I_NOEXEC|SB_I_NODEV;
This is a preparation patch that moves hide_pid and pid_gid parameters
to be stored inside procfs fs_info struct instead of making them per pid
namespace. Since we want to support multiple procfs instances we need to
make sure that all proc-specific parameters are also per-superblock.
Signed-off-by: Alexey Gladkov <redacted>
---
fs/proc/base.c | 18 +++++++++---------
fs/proc/inode.c | 9 ++++-----
fs/proc/root.c | 10 ++++++++--
include/linux/pid_namespace.h | 8 --------
include/linux/proc_fs.h | 9 +++++++++
5 files changed, 30 insertions(+), 24 deletions(-)
@@ -15,12 +15,6 @@structfs_pin;-enum{/* definitions for pid_namespace's hide_pid field */-HIDEPID_OFF=0,-HIDEPID_NO_ACCESS=1,-HIDEPID_INVISIBLE=2,-};-structpid_namespace{structkrefkref;structidridr;
@@ -39,8 +33,6 @@ struct pid_namespace {structuser_namespace*user_ns;structucounts*ucounts;structwork_structproc_work;-kgid_tpid_gid;-inthide_pid;intreboot;/* group exit code if this pidns was rebooted */structns_commonns;}__randomize_layout;
@@ -12,10 +12,19 @@ struct proc_dir_entry;structseq_file;structseq_operations;+/* definitions for hide_pid field */+enum{+HIDEPID_OFF=0,+HIDEPID_NO_ACCESS=1,+HIDEPID_INVISIBLE=2,+};+structproc_fs_info{structpid_namespace*pid_ns;structdentry*proc_self;/* For /proc/self */structdentry*proc_thread_self;/* For /proc/thread-self */+kgid_tpid_gid;+inthide_pid;};staticinlinestructproc_fs_info*proc_sb_info(structsuper_block*sb)