We previously spoke about permissions from the perspective of files, where the combination of file owner and permission mode bits allow you to refuse access to certain files by certain users.

When you attempt to access a file that you aren't permitted to, you get the "Operation not permitted" error message. This is not the only case when you can get that error message though, as some system calls are restricted.

Restricted to the root user

The traditional *nix permission model is that the root user (who has user-id of 0) can do anything they want, but other users are restricted to a reduced range of system calls.

For example, on a shared machine, you don't want every user to be able to call reboot(2), only the root user is allowed to do this, and the system administrator is assumed to be able to run commands as the root user.

Elevating privileges

The naive solution to users needing to gain elevated privileges to perform system administration is to share the password to the root user with responsible users, so they can log in as the root user when necessary.

This is not a good idea, especially if the machine is reachable by the wider internet, as it only requires someone to guess the password for the whole machine to be compromised.

The generally accepted solution is to use a tool like sudo, so that responsible users are allowed to run commands as the root user by entering their own passwords.

The sudo command works by having the setuid bit set on the executable, which means that the command is run as the root user. sudo therefore needs to perform its own permission checks to determine whether this is acceptable.

Restricted by capabilities

The traditional model is very all-or-nothing. This is fine for letting the system administrator do the work he needs to, but you might want to allow a user to start web services on the standard ports, while not allowing them to reboot the machine.

To make this work, the root user is granted a set of capabilities(7). Root usually has every capability to start with, so it remains compatible with the traditional access model, but processes spawned by a user can voluntarily drop capabilities they don't need.

To bind web services to low ports, processes need the CAP_NET_BIND_SERVICE capability, so it is possible to elevate privileges for a user by dropping every capability that isn't needed, so the user is able to bind web services, but is missing CAP_SYS_BOOT, so they can't reboot the machine.

Other approaches to permissions

Linux security modules

On top of the more traditional permissions model, there's mandatory access control schemes, which add extra permissions restrictions on top.

SELinux is often considered to be complicated beyond the understanding of mere mortals, which often means that even though it's enabled by default on Fedora, one of the first recommended debugging steps is to disable SELinux.

SMACK on the other hand, is designed to be simple, though is suffers from an unfortunate name.

Sandboxing

Instead of running general programs, you can have programs communicate in a restricted language to another entity that acts as a proxy, which can enforce its own logic for which operations are permitted.

Some examples of this are the JVM sandbox, which allows locking down Java programs, supple, which is roughly the same idea, but for Lua progras, and the Google Chrome sandbox, which allows JavaScript on web-pages to be safely executed.