To refuse all privileges (user and group), you need to drop the group in front of the user. Given that userid and groupid contain the identifiers of the user and group to which you want to go, and assuming that the effective identifiers are also root, this is achieved by calling setuid () and setgid () :
if (getuid() == 0) { /* process is running as root, drop privileges */ if (setgid(groupid) != 0) fatal("setgid: Unable to drop group privileges: %s", strerror(errno)); if (setuid(userid) != 0) fatal("setuid: Unable to drop user privileges: %S", strerror(errno)); }
If you are paranoid, you can try to regain your root privileges, which should fail. If this does not work, you will get help:
if (setuid(0) != -1) fatal("ERROR: Managed to regain root privileges?");
In addition, if you are still paranoid, you can seteuid () and setegid () , but this is not necessary, since setuid () and setgid () have already set all identifiers if the process belongs to root.
The list of additional groups is a problem because there is no POSIX function for setting additional groups (there are getgroups () , but no group groups ()). There is a BSD and Linux extension setgroups () that you can use, this is for you.
You must also chdir("/") or any other directory so that the process does not remain in the root directory.
Since your question is about Unix in general, this is a very general approach. Please note: on Linux, this is no longer the preferred approach. In current versions of Linux, you must set the CAP_NET_BIND_SERVICE feature in the executable file and run it as a regular user. No root access needed.
Juliano Jul 28 2018-10-21T00: 00-07
source share