As argued by others, it makes no sense to "remove" the root UID (which is represented on UNIX as the UID 0). I would go even further and state that it makes no sense to freeze a system into not having any means to provide new privileges. Note that this answer is very opiniated and vague, because the topic to cover is enormous. Let's first go through what being root means on *NIX. I'm going to comment on Linux since it's the most popular *NIX and it comes with specific methods. Hopefully others can cover the BSD families. Let's distinguish what root means in the context of :
- Discretionary Access Control
- Linux Security Modules
- UNIX capabilities
- User namespaces
Note that in any case, it makes absolutely no sense to blindly apply privilege restrictions system-wide to all binaries that currently run as root. Often these privileges exist for a reason. So you should read the summary below as explaining how you can affect specific services that you run for your unprivileged users and that you want to protect from exploitation.
Discretionary Access Control
Most of permissions for accessing files on *NIX systems are mandated by the DAC model. Many kernel interfaces and IPC mechanisms are abstracted as files so this is a rather important consideration. This is the model with an owner id, a group id and read/write/execute permissions for the owner, group members and other identities. It also comes with the suid and sgid bits, but I'll keep these off for now.
By default, UID 0 always bypasses DAC checks. This is because UID 0 has the CAP_DAC_OVERRIDE UNIX capability (see below). Processes that self-remove this capability will have to obey DAC, though most system files on your distribution are owned and writable by root anyway. Removing this capability may protect user files to an extent but will not protect the system itself. It is also very likely that a root user without this capability (and without the direct means to obtain other capabilities) can modify logind, your kernel image or other key files in order to corrupt or take over your system.
Linux Security Modules
On top of DAC checks, all system calls on Linux go through a pluggable kernel module that implements the Linux Security Module interface. Those could be used to deny privileges to root.
For instance, SELinux uses the concept of roles to this end. On all distributions' default policies that I know of, your login daemon will open your root sessions with a limited role, and you'd need to explicitly switch to a role called sysadm_r
before you can perform most traditional root operations. You do need to write policy to prevent root from being root-like with other roles. Still, since LSMs allow you to write a mandatory access control policy, you can effectively limit root privileges this way. The nice aspect however is that you can effectively trap user:role tuples into their roles, and you can provide roles selectively depending on how one logs in. This would allow limiting the scope of a specific root account system-wide.
UNIX capabilities
I don't want to paraphrase the man page on capabilities but essentially, capabilities allow user identities to interact with specific interfaces of the kernel. For instance, CAP_CHOWN allows you to modify the owner of a file. By default, root has most capabilities enabled (if I recall properly, CAP_MAC_ADMIN
or CAP_MAC_OVERRIDE
are not enabled by default) and other identities have none.
You can however remove some capabilities from your own set, so you can as a root process transform yourself into an unprivileged process, as long as you have the CAP_SET_FCAP
and CAP_SET_PCAP
capabilities. Note that it's been argued that many other capabilities can be used to re-gain full privileges. I cannot find the list of such capabilities right now but you should be aware that you need to seriously think about how a capability you leave to your root processes can be exploited for further compromise.
Whilst DAC controlled file accesses, capabilities, arguably, control system call access and behaviour (and the MAC LSM controls both). You must read the manuals of many calls in order to understand what each capability does.
There is criticism of the fitness of capabilities for Linux. Kerrisk has argued in "CAP_SYS_ADMIN: the new root" that some capabilities are so heavily relied upon that having them means having full powers. This suggests that you cannot just get rid of the concept of super-user alltogether. You will need to be extremely privileged at least to boot and set up your system, and to provide certain in-kernel services. In MAC systems that offer strong opportunities for confinement, you often run into the issue of needing to re-obtain a privilege (for instance, on SELinux, you might need to change role to sysadm_r
to perform a maintenance operation). Likewise, if you got rid of those capabilities, would you be able to (re)start new privileged services? Would the ability to do that not be equivalent to being fully privileged?
Linux User Namespaces
Namespaces allow you, very vaguely, to provide a different view of your system to processes run inside them. You can use mount namespaces to change what files a process and its children can see and modify, or network namespaces to provide different network interfaces and system configurations. This is useful for people who provide PaaS services, for instance. User namespaces allow you to map all of the user identities inside a namespace to a single one on the outside. This means that you can have a sub-system with a root user that can do whatever it wants inside the namespace and that is mapped to an unprivileged user outside the namespace.
What's the point of that exactly? If someone had an exploit on your kernel that allows them to escalate to root, the benefits of user namespaces are moot. However, if the exploit targets a suid binary, then an unprivileged process that gains access to root privileges inside its namespace will still be unable to affect the host OS. Note that confinement solutions like namespaces merely shift your boundaries of defense. Instead of proving that all your privileged processes are flawless and cannot be exploited, you must prove that a fully privileged process inside the namespace cannot affect the host OS via the communication channels you leave open between the host OS and the namespace. Ultimately if you need a privileged service inside your namespace to have access to a resource, then compromising that service will grant access to that resource.
What now? Can we provide entirely confined UNIXes?
All these methods above allow you to confine services to specific privileges (and with specific caveats, either in combinations (DAC+caps) or alone (LSM, namespaces). You can also combine them to provide defense in depth. However, the question of whether confining everything is beneficial is very independent from how you mediate privileges and represent the concept of full privilege (CAP_SYS_ADMIN, UID 0, un-namespaced privileged user, specific concept of your LSM).
When you write an operating system and you want it to be adapatable to its users' needs, you need to provide means to update and reconfigure it, and to run new services. If system maintenance involves operations such as updating your security services, access control policies, kernel and hardware modules, and so on, then you must either provide a way for a human user to act as a fully privileged actor, or you must have a third-party system that can adapt your OS and deploy the adapted version on top of your user's data. There are high security contexts where the latter might be desirable (and very frankly this is, conceptually, as simple as running a VM). In the case of general-purpose computing by a population of users that self-maintain their systems, however, you cannot get rid of fully privileged identities.