In code like this in a daemon:
// run as root, after initgroups(...), setgid(...)
setuid(user);
const char* args[] = {"./userbinary",0};
execv("userbinary", args);
_exit(1);
there's an obvious problem where the user can attach to the process between the calls to setuid
and exec[lvpe]
, and read out all the process's memory, including sensitive variables and state.
A workaround I use is like this (obviously, all error handling ommitted):
// run as root in daemon
const char* args = {"/usr/bin/mysetuid", uidStr, "./userbinary", 0};
execv("/usr/bin/mysetuid", args);
_exit(1);
// mysetuid.c:
int main(int arc, char* argv[]) {
setuid(atoi(argv[1]));
execv(argv[2], argv+2);
exit(1);
}
What is the "standard" way of doing this operation? Using a helper binary seems safest, but I can't find other applications that do this. For example, OpenSSH just relies on the fact that each user's connection gets its own process, so the setuid
is always done from a process that has pretty much a blank slate.