The correct way to run setuid programs in C

I have a process with 4750 permissions. There are two users on my Linux system. The root user and the appz user. The process inherits the permissions of the process manager, which runs as the appz user.

I have two main procedures:

void do_root (void) { int status; status = seteuid (euid); if (status < 0) { exit (status); } } /* undo root permissions */ void undo_root (void) { int status; status = seteuid (ruid); if (status < 0) { exit (status); } status = setuid(ruid); if (status < 0) { exit (status); } } 

My thread is as follows:

 int main() { undo_root(); do some stuff; do_root(); bind( port 80); //needs root perm undo_root(); while(1) { accept commads() if ( commands needs root user access) { do_root(); execute(); undo_root(); } } 

As you can see, I want to execute some commands with root privileges. I am trying to temporarily remove permissions, and if tasks need root access, I end the command between calling do_root and undo_root.

However, it seems my program is not working.

What is the canonical way to do this?

+6
source share
3 answers

The old-school way is to use both set_uot and undo_root setreuid () for swap ruid and euid:

 setreuid(geteuid(), getuid()); 

This is acceptable if the program is small enough to perform a full security audit.

The new school method is much more complicated and includes fork () with a child element that takes directives for what to do as root, and then runs setuid (getuid ()) to automatically remove the root in the parent object. The child is responsible for checking all the directives that he receives. For a large enough program, this reduces the amount of code that must be checked by the security system, and allows the user to control the process using task management or kill it, etc.

+5
source

There is an article called β€œ Setuid Demystified β€œ Hao Chen, ”by David Wagner and Drew Dean. It was introduced in USENIX 2002. It describes how setuid() and transitions work in great detail (fixed since 2002). Worth reading (several times - I have to be overdue after a year or two).

Basically, like Petesh , it is noted in the comment that when a process with EUID 0 does setuid(nuid) with nuid != 0 , there is no way back to root (EUID 0). And indeed, it is very important that this be so. Otherwise, when you log in, the root process that logs you in cannot limit your own privileges - you can return to root . The stored UID complicates the situation, but I don’t think it affects the one-way EUID 0 trap by doing setuid() .

+5
source

The setuid help page states the following:

... the set-user-ID-root program that wants to temporarily remove the privilege root, accept the identity of a non-root user, and then restore root privileges subsequently cannot use setuid ()

So you cannot use setuid() . You should use seteuid() and possibly setreuid() . See the Setuid sample program for details .

+2
source

Source: https://habr.com/ru/post/908534/


All Articles