Give a user privileges to switch process UID, GID

privilegesrootusers

I'm writing an application that create worker processes run under other users credential. This program works under root. However, I want to run it under a less privileged account.

Is there any way I can give a user account the permission to assign UID, GID for the process it creates?

In other word, is there anyway to limit/grant a user privilege to certain set of syscalls? Thanks!

Best Answer

Giving a process the right to change its UID is equivalent to giving it the right to run as root, since it can just change its UID to root. So even if you did that, there'd be no benefit.

You can improve the security of this setup by reducing the risk that the program can be tricked into doing something unintended as root. This won't reduce the impact of a complete compromise (if an attacker is able to make your program run arbitrary code), but it can reduce the impact of a partial compromise (where the attacker is only able to convince your program to do some specific thing, e.g. to read a file and display it). To reduce the risk, reduce the window of time during which the program runs as root. Make it run as a dedicated user, but keep its real UID set to 0. When the program needs to be root, it temporarily switches its effective UID to 0, and then switches back.

Note that this is not really practical in a multithreaded program since the user ID is for a whole process, not per thread.

For better robustness and security, implement privilege separation: split your program into two processes, one that runs as root and one that runs as a dedicated user. The process that runs as root should do as little as possible. It takes requests from the other process, validates them to the extent possible, and performs them. Then, even if the other process is buggy, the most it can do is issue valid requests.

For simple needs, rather than write a program that runs as root, you may be able to have a sudo rule that directly allows the main program to run commands as a third user. Instead of relying on an intermediate root program to perform validation, you can embed the validation in the sudo rule, e.g.

myapp_user ALL = (ALL:ALL) validate_and_run

This allows myapp_user to run a command as any user, but the command has to be validate_and_run (with any arguments).

Related Question