I think we can distinguish two uses of setuid:
- start a non-privileged process, at login, or when init starts a service
- as a deputy to enable a lesser privileged user to do some task
To start the non-privileged process, I would suggest the ideal would be something like spawnas(), which only root can call, and specifies the non-root user to start the process as. (I have never liked fork/exec, because it is too easy to accidentally pass stuff to the child process from the parent when one didn't mean to. I would prefer spawn, with explicit specification of desired child process state, by use of some extensible data structure. Fork is dumb, because copy-on-write is the rare case, the common is fork-exec which is equivalent to spawn. And with multiple threads, who ever really needs fork anyway?)
Then, all the deputy uses can just become daemons accessible over some local domain socket or some RPC/LPC protocol (maybe implemented on top of that). Maybe with the ability to pass file descriptors/handles from the daemon back to its unprivileged caller... There should be some security checking, over what handles it can pass. (Permissions on objects could by default be non-delegable, unable to be passed to another process -- an extra permission, e.g. "read" vs "delegate read", could be needed to pass the handle to another process...)
Posted Nov 30, 2010 10:27 UTC (Tue) by mpr22 (subscriber, #60784)
[Link]
Personally, I'd rather write if (!(child = fork())) { do_stuff(); execve(foo, bar, baz); } than ram_stuff_into_structure(&foo); child = spawn(&foo); } because the former allows me to do arbitrary stuff between fork and exec, while the latter only allows me to do things the library / kernel designers have foreseen.
As for "And with multiple threads, who ever really needs fork anyway?", how about "anyone who wants to get a useful program-readable error indication when the activity that's just been kicked off corrupts its heap, rather than having the whole kit and kaboodle come crashing down with a SEGV"?