Re: launchd daemon, spawning children?
Re: launchd daemon, spawning children?
- Subject: Re: launchd daemon, spawning children?
- From: Terry Lambert <email@hidden>
- Date: Wed, 1 Oct 2008 12:21:19 -0700
On Oct 1, 2008, at 3:40 AM, Mario Emmenlauer wrote:
Hi Terry and List,
Terry Lambert wrote:
On Sep 26, 2008, at 2:37 AM, Mario Emmenlauer wrote:
Damien Sorresso wrote:
The rules of setuid(2) have evolved into a vastly complex morass
with subtle variations on different platforms. Entire papers have
been written about this behavior.
You name it. I will look for a good tutorial, though Terry's
suggestion
contained a nice start.
The primary paper on UNIX setuid() is:
Setuid Demystified
Hao Chen, David Wagner, Drew Dean
Proceedings of the 11th USENIX Security Symposium
<www.cs.berkeley.edu/~daw/papers/setuid-usenix02.pdf>
Thanks a lot, the paper is great!
I finally ended up with something like (pseudocode):
fork();
if(pid == 0) {
setgroups();
setgid();
You probably actually want:
setgid();
syscall(SYS_initgroups, int ngroups, const gid_t *gidset, uid_t gmuid)
If you do not set the group membership uid, and do it without any
other modifications of the credential, save the final setuid(), then
you will opt out of external group resolution. This means that if you
have put a user into more than 16 groups in DirectoryServices, you wil
only see 16 of them, and due to ordering ambiguity, you will only be
guaranteed that the primary group ID for the user will be in that list
of 16.
As I said, it gets complicated.
setuid();
close_nonstd_file_descriptors();
execve("/path/to/worker");
_exit();
} else {
while(1) { waitpid(WNONBLOCK); usleep(1000); }
}
This works very well, and makes sure the worker process can not gain
higher permissions than it should have. Don't mind the while(1) above,
in practice I have a network connection open between worker and server
to get error-feedback, so the server won't get stuck.
In general, we do not want you to establish your own sessions, and
would prefer that you use /bin/login to do session management and
support the utmp/utmpx interfaces for process accounting and
knowing who is logged into your system, etc.; otherwise, things get
more complicated fast, in order to support those interfaces, since
you have to (1) maintain privilege in order to access the files to
write out the closure records on sessions started by you (login
does this - it hangs around until its children go away), and (2)
deal with PAM and all the other things login deals with for
authenticating you to the system.
Your suggestion to use login seems reasonable. Can someone sketch an
outline how an application (daemon) would use login to start a new
process as a certain user? Is that what you meant:
execve("/bin/login -f worker_user /path/to/worker")
Typically, it's not used for daemons. daemons are expected to be
started by launchd, which will do the session establishing.
Establishing your own session is intended to be limited to interactive
sessions. If you have more questions about interactive sessions and
the login program, you should look at the sources for sshd or ftpd.
One last question: If "worker_user" is the current GUI-user, all his
applications get killed on logout. Is there a way around this (or
would
using 'login' also solve this issue?)
The logout operation for non-GUI applications sends either a SIGHUP
(the correct signal), or a SIGTERM (not the correct signal). You can
ignore or catch these signals with a signal handler, although if you
ignore SIGTERM, you will delay shutdowns.
In general, daemons running as that user are not kiplled unless they
are in the process group, or their parent is the per-session launchd.
Otherwise, you would not be able to ssh into a machine and log out of
a GUI and not have it kill your ssh (which it doesn't do).
-- Terry
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden