Thread (88 messages) 88 messages, 7 authors, 2019-02-12

Re: [PATCH] LSM: add SafeSetID module that gates setid calls

From: Micah Morton <mortonm@chromium.org>
Date: 2018-11-01 16:22:42

On Thu, Nov 1, 2018 at 9:11 AM Micah Morton [off-list ref] wrote:
On Wed, Oct 31, 2018 at 11:07 PM Serge E. Hallyn [off-list ref] wrote:
quoted
On Wed, Oct 31, 2018 at 09:02:45PM +0000, Serge E. Hallyn wrote:
quoted
Quoting mortonm@chromium.org (mortonm@chromium.org):
quoted
From: Micah Morton <mortonm@chromium.org>

SafeSetID gates the setid family of syscalls to restrict UID/GID
transitions from a given UID/GID to only those approved by a
system-wide whitelist. These restrictions also prohibit the given
UIDs/GIDs from obtaining auxiliary privileges associated with
CAP_SET{U/G}ID, such as allowing a user to set up user namespace UID
mappings. For now, only gating the set*uid family of syscalls is
supported, with support for set*gid coming in a future patch set.

Signed-off-by: Micah Morton <mortonm@chromium.org>
---

NOTE: See the TODO above setuid_syscall() in lsm.c for an aspect of this
code that likely needs improvement before being an acceptable approach.
I'm specifically interested to see if there are better ideas for how
this could be done.

 Documentation/admin-guide/LSM/SafeSetID.rst |  94 ++++++
 Documentation/admin-guide/LSM/index.rst     |   1 +
 arch/Kconfig                                |   5 +
 arch/arm/Kconfig                            |   1 +
 arch/arm64/Kconfig                          |   1 +
 arch/x86/Kconfig                            |   1 +
 security/Kconfig                            |   1 +
 security/Makefile                           |   2 +
 security/safesetid/Kconfig                  |  13 +
 security/safesetid/Makefile                 |   7 +
 security/safesetid/lsm.c                    | 334 ++++++++++++++++++++
 security/safesetid/lsm.h                    |  30 ++
 security/safesetid/securityfs.c             | 189 +++++++++++
 13 files changed, 679 insertions(+)
 create mode 100644 Documentation/admin-guide/LSM/SafeSetID.rst
 create mode 100644 security/safesetid/Kconfig
 create mode 100644 security/safesetid/Makefile
 create mode 100644 security/safesetid/lsm.c
 create mode 100644 security/safesetid/lsm.h
 create mode 100644 security/safesetid/securityfs.c
diff --git a/Documentation/admin-guide/LSM/SafeSetID.rst b/Documentation/admin-guide/LSM/SafeSetID.rst
new file mode 100644
index 000000000000..e7d072124424
--- /dev/null
+++ b/Documentation/admin-guide/LSM/SafeSetID.rst
@@ -0,0 +1,94 @@
+=========
+SafeSetID
+=========
+SafeSetID is an LSM module that gates the setid family of syscalls to restrict
+UID/GID transitions from a given UID/GID to only those approved by a
+system-wide whitelist. These restrictions also prohibit the given UIDs/GIDs
+from obtaining auxiliary privileges associated with CAP_SET{U/G}ID, such as
+allowing a user to set up user namespace UID mappings.
+
+
+Background
+==========
+In absence of file capabilities, processes spawned on a Linux system that need
+to switch to a different user must be spawned with CAP_SETUID privileges.
+CAP_SETUID is granted to programs running as root or those running as a non-root
+user that have been explicitly given the CAP_SETUID runtime capability. It is
+often preferable to use Linux runtime capabilities rather than file
+capabilities, since using file capabilities to run a program with elevated
+privileges opens up possible security holes since any user with access to the
+file can exec() that program to gain the elevated privileges.
Not true, see inheritable capabilities.  You also might look at ambient
capabilities.
So for example with pam_cap.so you could have your N uids each be given
the desired pI, and assign the corrsponding fIs to the files they should
be able to exec with privilege.  No other uids will run those files with
privilege.  *1
Sorry, what are "pl" and "fls" here? "Privilege level" and "files"?
quoted
Can you give some more details about exactly how you see SafeSetID being
used?
Sure. The main use case for this LSM is to allow a non-root program to
transition to other untrusted uids without full blown CAP_SETUID
capabilities. The non-root program would still need CAP_SETUID to do
any kind of transition, but the additional restrictions imposed by
this LSM would mean it is a "safer" version of CAP_SETUID since the
non-root program cannot take advantage of CAP_SETUID to do any
unapproved actions (i.e. setuid to uid 0 or create/enter new user
namespace). The higher level goal is to allow for uid-based sandboxing
of system services without having to give out CAP_SETUID all over the
place just so that non-root programs can drop to
even-further-non-privileged uids. This is especially relevant when one
non-root daemon on the system should be allowed to spawn other
processes as different uids, but its undesirable to give the daemon a
basically-root-equivalent CAP_SETUID.
quoted
I'm still not quite clear on whether you want N completely unprivileged
uids to be used by some user (i.e. uid 1000), or whether one or more of
those should also have some privileged, or whether one of the uids might
or might not b uid 0.  Years ago I used to use N separate uids to
somewhat segragate workloads on my laptop, and I'd like my browser to
do something like that.  Is that the kind of uid switching you have
in mind?
"N completely unprivileged uids to be used by some user (i.e. uid
1000)" is the closest description of what this LSM has in mind. For
example, uid 123 is some system service that needs runtime
capabilities X, Y and Z and a bunch of DBus permissions associated
with uid 123, but also wants to spawn another program without any of
these capabilities/permissions. In this case we would like to avoid
giving the system service CAP_SETUID.
To clarify: "spawn another program *as a different uid* without any..."
quoted
-serge

*1 And maybe with one of the p9auth/factotem proposals out there you
could have a userspace daemon hand out the tokens for setuid, but that's
getting "out there" and probably derailing this conversation :)
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help