xref: /openbmc/linux/Documentation/admin-guide/LSM/SafeSetID.rst (revision cdd38c5f1ce4398ec58fec95904b75824daab7b5)
1aeca4e2cSMicah Morton=========
2aeca4e2cSMicah MortonSafeSetID
3aeca4e2cSMicah Morton=========
4aeca4e2cSMicah MortonSafeSetID is an LSM module that gates the setid family of syscalls to restrict
5aeca4e2cSMicah MortonUID/GID transitions from a given UID/GID to only those approved by a
65294bac9SThomas Cedenosystem-wide allowlist. These restrictions also prohibit the given UIDs/GIDs
7aeca4e2cSMicah Mortonfrom obtaining auxiliary privileges associated with CAP_SET{U/G}ID, such as
85294bac9SThomas Cedenoallowing a user to set up user namespace UID/GID mappings.
9aeca4e2cSMicah Morton
10aeca4e2cSMicah Morton
11aeca4e2cSMicah MortonBackground
12aeca4e2cSMicah Morton==========
13aeca4e2cSMicah MortonIn absence of file capabilities, processes spawned on a Linux system that need
14aeca4e2cSMicah Mortonto switch to a different user must be spawned with CAP_SETUID privileges.
15aeca4e2cSMicah MortonCAP_SETUID is granted to programs running as root or those running as a non-root
16aeca4e2cSMicah Mortonuser that have been explicitly given the CAP_SETUID runtime capability. It is
17aeca4e2cSMicah Mortonoften preferable to use Linux runtime capabilities rather than file
18aeca4e2cSMicah Mortoncapabilities, since using file capabilities to run a program with elevated
19aeca4e2cSMicah Mortonprivileges opens up possible security holes since any user with access to the
20aeca4e2cSMicah Mortonfile can exec() that program to gain the elevated privileges.
21aeca4e2cSMicah Morton
22aeca4e2cSMicah MortonWhile it is possible to implement a tree of processes by giving full
23aeca4e2cSMicah MortonCAP_SET{U/G}ID capabilities, this is often at odds with the goals of running a
24aeca4e2cSMicah Mortontree of processes under non-root user(s) in the first place. Specifically,
25aeca4e2cSMicah Mortonsince CAP_SETUID allows changing to any user on the system, including the root
26aeca4e2cSMicah Mortonuser, it is an overpowered capability for what is needed in this scenario,
27aeca4e2cSMicah Mortonespecially since programs often only call setuid() to drop privileges to a
28aeca4e2cSMicah Mortonlesser-privileged user -- not elevate privileges. Unfortunately, there is no
29aeca4e2cSMicah Mortongenerally feasible way in Linux to restrict the potential UIDs that a user can
30aeca4e2cSMicah Mortonswitch to through setuid() beyond allowing a switch to any user on the system.
31aeca4e2cSMicah MortonThis SafeSetID LSM seeks to provide a solution for restricting setid
32aeca4e2cSMicah Mortoncapabilities in such a way.
33aeca4e2cSMicah Morton
34aeca4e2cSMicah MortonThe main use case for this LSM is to allow a non-root program to transition to
35aeca4e2cSMicah Mortonother untrusted uids without full blown CAP_SETUID capabilities. The non-root
36aeca4e2cSMicah Mortonprogram would still need CAP_SETUID to do any kind of transition, but the
37aeca4e2cSMicah Mortonadditional restrictions imposed by this LSM would mean it is a "safer" version
38aeca4e2cSMicah Mortonof CAP_SETUID since the non-root program cannot take advantage of CAP_SETUID to
39aeca4e2cSMicah Mortondo any unapproved actions (e.g. setuid to uid 0 or create/enter new user
40aeca4e2cSMicah Mortonnamespace). The higher level goal is to allow for uid-based sandboxing of system
41aeca4e2cSMicah Mortonservices without having to give out CAP_SETUID all over the place just so that
42aeca4e2cSMicah Mortonnon-root programs can drop to even-lesser-privileged uids. This is especially
43aeca4e2cSMicah Mortonrelevant when one non-root daemon on the system should be allowed to spawn other
44aeca4e2cSMicah Mortonprocesses as different uids, but its undesirable to give the daemon a
45aeca4e2cSMicah Mortonbasically-root-equivalent CAP_SETUID.
46aeca4e2cSMicah Morton
47aeca4e2cSMicah Morton
48aeca4e2cSMicah MortonOther Approaches Considered
49aeca4e2cSMicah Morton===========================
50aeca4e2cSMicah Morton
51aeca4e2cSMicah MortonSolve this problem in userspace
52aeca4e2cSMicah Morton-------------------------------
53aeca4e2cSMicah MortonFor candidate applications that would like to have restricted setid capabilities
54aeca4e2cSMicah Mortonas implemented in this LSM, an alternative option would be to simply take away
55aeca4e2cSMicah Mortonsetid capabilities from the application completely and refactor the process
56aeca4e2cSMicah Mortonspawning semantics in the application (e.g. by using a privileged helper program
57aeca4e2cSMicah Mortonto do process spawning and UID/GID transitions). Unfortunately, there are a
58aeca4e2cSMicah Mortonnumber of semantics around process spawning that would be affected by this, such
590e390189SChristian Kujauas fork() calls where the program doesn't immediately call exec() after the
60aeca4e2cSMicah Mortonfork(), parent processes specifying custom environment variables or command line
61aeca4e2cSMicah Mortonargs for spawned child processes, or inheritance of file handles across a
62aeca4e2cSMicah Mortonfork()/exec(). Because of this, as solution that uses a privileged helper in
63aeca4e2cSMicah Mortonuserspace would likely be less appealing to incorporate into existing projects
64aeca4e2cSMicah Mortonthat rely on certain process-spawning semantics in Linux.
65aeca4e2cSMicah Morton
66aeca4e2cSMicah MortonUse user namespaces
67aeca4e2cSMicah Morton-------------------
68aeca4e2cSMicah MortonAnother possible approach would be to run a given process tree in its own user
69aeca4e2cSMicah Mortonnamespace and give programs in the tree setid capabilities. In this way,
70aeca4e2cSMicah Mortonprograms in the tree could change to any desired UID/GID in the context of their
71aeca4e2cSMicah Mortonown user namespace, and only approved UIDs/GIDs could be mapped back to the
72aeca4e2cSMicah Mortoninitial system user namespace, affectively preventing privilege escalation.
73aeca4e2cSMicah MortonUnfortunately, it is not generally feasible to use user namespaces in isolation,
74aeca4e2cSMicah Mortonwithout pairing them with other namespace types, which is not always an option.
750e390189SChristian KujauLinux checks for capabilities based off of the user namespace that "owns" some
76aeca4e2cSMicah Mortonentity. For example, Linux has the notion that network namespaces are owned by
77aeca4e2cSMicah Mortonthe user namespace in which they were created. A consequence of this is that
78aeca4e2cSMicah Mortoncapability checks for access to a given network namespace are done by checking
79aeca4e2cSMicah Mortonwhether a task has the given capability in the context of the user namespace
80aeca4e2cSMicah Mortonthat owns the network namespace -- not necessarily the user namespace under
81aeca4e2cSMicah Mortonwhich the given task runs. Therefore spawning a process in a new user namespace
82aeca4e2cSMicah Mortoneffectively prevents it from accessing the network namespace owned by the
83aeca4e2cSMicah Mortoninitial namespace. This is a deal-breaker for any application that expects to
84aeca4e2cSMicah Mortonretain the CAP_NET_ADMIN capability for the purpose of adjusting network
85aeca4e2cSMicah Mortonconfigurations. Using user namespaces in isolation causes problems regarding
86aeca4e2cSMicah Mortonother system interactions, including use of pid namespaces and device creation.
87aeca4e2cSMicah Morton
88aeca4e2cSMicah MortonUse an existing LSM
89aeca4e2cSMicah Morton-------------------
90aeca4e2cSMicah MortonNone of the other in-tree LSMs have the capability to gate setid transitions, or
91aeca4e2cSMicah Mortoneven employ the security_task_fix_setuid hook at all. SELinux says of that hook:
92aeca4e2cSMicah Morton"Since setuid only affects the current process, and since the SELinux controls
93aeca4e2cSMicah Mortonare not based on the Linux identity attributes, SELinux does not need to control
94aeca4e2cSMicah Mortonthis operation."
95aeca4e2cSMicah Morton
96aeca4e2cSMicah Morton
97aeca4e2cSMicah MortonDirections for use
98aeca4e2cSMicah Morton==================
99aeca4e2cSMicah MortonThis LSM hooks the setid syscalls to make sure transitions are allowed if an
100aeca4e2cSMicah Mortonapplicable restriction policy is in place. Policies are configured through
1015294bac9SThomas Cedenosecurityfs by writing to the safesetid/uid_allowlist_policy and
1025294bac9SThomas Cedenosafesetid/gid_allowlist_policy files at the location where securityfs is
1035294bac9SThomas Cedenomounted. The format for adding a policy is '<UID>:<UID>' or '<GID>:<GID>',
1045294bac9SThomas Cedenousing literal numbers, and ending with a newline character such as '123:456\n'.
1055294bac9SThomas CedenoWriting an empty string "" will flush the policy. Again, configuring a policy
1065294bac9SThomas Cedenofor a UID/GID will prevent that UID/GID from obtaining auxiliary setid
1075294bac9SThomas Cedenoprivileges, such as allowing a user to set up user namespace UID/GID mappings.
1085294bac9SThomas Cedeno
1095294bac9SThomas CedenoNote on GID policies and setgroups()
110*afc74ce7SMauro Carvalho Chehab====================================
1115294bac9SThomas CedenoIn v5.9 we are adding support for limiting CAP_SETGID privileges as was done
1125294bac9SThomas Cedenopreviously for CAP_SETUID. However, for compatibility with common sandboxing
1135294bac9SThomas Cedenorelated code conventions in userspace, we currently allow arbitrary
1145294bac9SThomas Cedenosetgroups() calls for processes with CAP_SETGID restrictions. Until we add
1155294bac9SThomas Cedenosupport in a future release for restricting setgroups() calls, these GID
1165294bac9SThomas Cedenopolicies add no meaningful security. setgroups() restrictions will be enforced
1175294bac9SThomas Cedenoonce we have the policy checking code in place, which will rely on GID policy
1185294bac9SThomas Cedenoconfiguration code added in v5.9.
119