TL;DR: Avoid using negative permissions; on modern Linux systems, they can be circumvented.
Linux offers a diverse range of methods for implementing file permissions. In addition to the traditional discretionary access control (DAC), it also supports access control lists (ACL) and mandatory access control (MAC). Typically, all of these methods operate in a positive manner, meaning that each established permission configuration grants power. By default, nothing is permitted. This approach is also occasionally termed white or allow listing. However, both DAC and ACL do allow the implementation of negative permissions. Negative permissions deny access to certain users or groups while everybody else retains access. This practice is much less common and is widely seen as a poor security practice within the community.
With the advent of Linux containers, the landscape has shifted, rendering negative permissions not only a poor practice but also susceptible to bypass attacks. In contemporary Linux systems, there’s a significant likelihood that users can sidestep negative permissions and potentially gain entry to protected files.
Let’s consider a scenario where everyone has access to the
/usr/share/games folder. However, there’s a desire to prevent specific users from playing games. To achieve this, a new group called
nogames is established, and a negative permission is implemented to deny access for members belonging to this group.
john are effectively restricted from accessing the
/usr/share/games directory. This outcome is achieved due to the priority sequence:
user DAC entries take precedence over
group takes precedence over
Given that both
john belong to the
nogames group, the permissions established for the
nogames group take precedence, resulting in no granted permissions for them.
Conversely, for all other users, either the
user or the
other entities come into play.
The same objective can also be accomplished using Access Control Lists (ACLs) in place of discretionary access control (DAC). For instance, you can implement an ACL using a command like
setfacl -m g:nogames:--- /usr/share/games.
Certainly, if a user manages to remove themselves from the
nogames group, access would be restored.
setgroups()1 system call enables the modification of supplementary groups associated with the current process.
Naturally, such an operation requires privileged capabilities, specifically the
This mechanism highlights the significance of managing privileges and group memberships to effectively uphold the desired access controls.
With the advent of Linux containers, particularly user namespaces, the dynamics have shifted.
In a user namespace, an unprivileged user possesses all capabilities.
However, every action taking place within the namespace is associated with the user and group IDs of the namespace’s creator.
For enabling rootless container engines like
shadow-utils package includes a lesser-known toolkit:
These tools are either set-uid-root or possess the file capability
By utilizing these tools, users can establish a fresh user namespace and set up UID and GID mappings that target distinct IDs from those of the invoking task.
These mappings are maintained in
When a user is created, the
useradd tool configures these designated subordinate IDs.
Having multiple group ID mappings in place empowers a process within a user namespace once again to employ the
setgroups() syscall, allowing it to shed supplementary groups at its discretion!
unshare tool internally employs
/etc/subgid, we know that the user named
bob can utilize the subordinate group ID
podman in rootless mode can also be utilized to achieve the same result.
An attentive reader might wonder about negative permissions based on users, as we’ve mostly talked about groups so far.
Consider a scenario involving negative ACLs like this: let’s say we want to prevent user
bob from accessing games using an ACL command like
setfacl -m u:bob:--- /usr/share/games.
Once again, using
unshare along with
newuidmap proves to be effective.
However, this time, it doesn’t involve dropping additional groups.
Instead, it works by changing the effective user ID to one within a specific range.
At first, the idea that dropping or changing group memberships might cause problems wasn’t considered when user namespaces were added. This was mainly because people didn’t think about situations where permissions work in a negative way. It was assumed that if you leave a group, you’d have less power, and on Linux diminishing one’s own authority is usually okay. Yet, it didn’t take long to realize4 that dropping groups could actually give more power when dealing with negative permissions. This discovery led to an issue known as CVE-2014-8989, which was quickly fixed in Linux version 3.19.
In 2018, it was discovered that version 4.5 of the
shadow-utils package introduced a new tool named
This tool can be used to create more complex mappings for group IDs within user namespaces.
Consequently, it reinstates the ability to drop group memberships using the
This issue was given the tracking identifier CVE-2018-7169.
The resolution adopted by some Linux distributions was to exclude this tool from their packages.
newuidmap assists users in changing their user ID to one within an authorized range, as configured in
This maneuver can also serve to circumvent negative permissions based on user settings.
Other potential solutions also focused on the
shadow-utils package itself9, but as of now, they haven’t gained significant traction.
Ultimately, by 2021, a general agreement was reached to move away from supporting negative permissions and to acknowledge the reality that they can be circumvented10.
In 2023, Richard rediscovered the problem and opted to comprehensively document it across multiple Linux manual pages11.
Negative permissions have consistently been regarded as bad practice and often treated as theoretical concept. With the incorporation of Linux containers, negative permissions can now be evaded.
If you find yourself reliant on them, consider one of the following actions:
newgidmapis present. As of 2023, these two tools are the primary gateways for bypassing such permissions. However, this situation might change in the future.
kernel.unprivileged_userns_cloneto disable user namespaces only for unprivileged users.
Finally, it is worth noting that there is still effort to tame