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