[launchd-dev] UserName ignored on per-user LaunchAgents

Kevin Van Vechten kvv at apple.com
Wed Dec 5 00:48:37 PST 2007

On Dec 4, 2007, at 7:39 PM, Jeremy Reichman wrote:

> This may be something of a "duh" but I'm curious if it is  
> intentional and
> immutable that per-user LaunchAgents, such as those a sys admin  
> might want
> to stuff into /Library/LaunchAgents, ignore the "UserName" key.

Yes, it's intentional.  LaunchAgents are executed by the per-user  
launchd.  As a non-root process, it does not have the privilege to  
setuid(2) to another user, hence the UserName key is ignored.

> In launchd.plist's man page:
> "UserName <string>
> This optional key specifies the user to run the job as. The default  
> is the
> user who submitted the job to launchd."

This was written before the advent of the per-user launchd.  It should  
be revised to indicate this key is honored by the root launchd only  
(for use by LaunchDaemons).

> Why do I want to specify it? Well, launchd tasks have certain  
> advantages
> over LoginHook (and LogoutHook). If I could replace LoginHook  
> scripts --
> which, let's face it, are limited in that they have to be called by  
> a single
> script parent script (similar to `/usr/sbin/periodic`) -- with launchd
> tasks, I'd much prefer to do so. For one thing, there's no  
> modification of
> the loginwindow plist -- and the use of individual launchd jobs  
> would make
> it much easier to run multiple tasks.
> The most obvious way to accomplish that is with a LaunchAgent, but
> Login|LogoutHook run as root. Hence the problem. If your LoginHook- 
> type
> tasks need root access for whatever reason, then the obvious launchd  
> way to
> set that up is with the UserName key in your job plist. But it  
> doesn't work.
> I can see the wisdom of ignoring the key, but if a sys admin has  
> placed a
> job in /Library/LaunchAgents, and that directory is installed with the
> system using restrictive permissions, and the job is owned by root,  
> there
> would seem to be several adequate safeguards in place to make  
> malicious use
> difficult. (Application Launch Restrictions are already depending on  
> the
> filesystem location and permissions, at least in managed  
> environments, so it
> would seem that launchd could do so as well.) I would be supportive  
> of other
> reasonable safeguards besides these, too, including script signing  
> and more.
> Besides asking whether ignoring the UserName key is meant to be this  
> way and
> could be changed in the future if enhancement requests were filed,  
> is there
> another way to replace the hooks with launchd?

Let's step back to a time before launchd and consider the case of an  
ordinary Cocoa application that needs to perform a privileged  
operation.  Since there's no "UserName" key available in the  
Info.plist, the application must invoke a privileged helper tool  
(setuid binary, gated by AuthorizationExecWithPrivilege).

With launchd, it's now possible to get rid of the setuid binary (which  
avoids a whole class of potential privilege escalation  
vulnerabilities) and replace it with a LaunchDaemon that executes in a  
privileged context.  The Cocoa application can send an IPC message to  
the Daemon, and the daemon can perform the privileged operation  
(Authorization API can still be used to create an "external form" that  
can be validated across the IPC channel).

A LaunchAgent, like the Cocoa application example, runs as the user --  
in fact they're running in the same context.  If it needs to perform a  
privileged operation, it can send an IPC message to a LaunchDaemon  
running in a privileged context to perform said operation.

- Kevin

More information about the launchd-dev mailing list