Re: [systemd-devel] euid 0 not honored authenticating control socket?

2016-01-25 Thread Lennart Poettering
On Thu, 21.01.16 18:12, Charles Duffy (char...@dyfis.net) wrote:

> Howdy --
> 
> I have a setuid-root executable from which I'm trying to start or stop a
> service. However, when invoking systemctl from this executable -- for which
> geteuid() returns 0 -- the control socket is rejected when the ruid does
> not match (such that the executable was invoked from a less-privileged
> user).
> 
> 2042 17:02:00.508893788 0 systemd (1) > recvmsg
> fd=14(883f648b4280->883f648b4980 /run/systemd/private)
> 2043 17:02:00.508897318 0 systemd (1) < recvmsg res=45 size=45 data=.AUTH
> EXTERNAL 30..NEGOTIATE_UNIX_FD..BEGIN.. tuple=NULL
> 
> 2068 17:02:00.510329428 0 systemd (1) > sendmsg
> fd=14(883f648b4280->883f648b4980 /run/systemd/private) size=24
> tuple=NULL
> 2069 17:02:00.510344760 0 systemd (1) < sendmsg res=24
> data=REJECTED..ERROR..ERROR..
> 
> What's going on, and why?

D-Bus authentication includes the UID in text form in the protocol,
and compares that with the kernel supplied connection metadata
included in the socket ucred stuff. The former currently passes along
the UID, the latter the EUID. If you invoke systemctl with uid != euid
then we'll consider the two bits of data to be out of sync, and not
allow the connection.

Of course, one could argue that if euid is 0, we should accept any
value for the uid included in the auth protocol.  However, the current
logic instead suggests: if you have the rights to fake creds data then
please also fake the data in the ucred structure... Which however
won't take place in systemctl however, since it doesn't expect to be
used from suid binaries...

Now, I'd be willing to change the current logic: 

a) we could either pass the UID in both ucred and the auth
   protocol. In this case, the connection would be conisdered coming
   from the UID.

b) or we could pass the EUID in both. In this case the connection
   would be considered coming from the EUID.

c) or we could continue to pass the UID in the auth proto, but allow
   it to be any desired value if the ucred-indicated EUID is 0. The
   auth proto would count, and hence the connection would be
   considered coming from the the UID.

d) or we could continue to pass the UID in the auth proto, but ignore
   it completely if the ucred-indicated EUID is 0. The ucred supplied
   euid would count in this case, and the connection would be coming
   from the EUID.

From all these options, I figure b) or d) would be the behaviour you
would prefer, as only then the connection would be owned by the EUID
and thus your euid of root would be considered for method calls.

However I am pretty sure a) or c) would be more in-line with UNIX
logic: i.e. the euid data would be used for permissions but the
ownership of objects such as the connection would still be bound to
the uid.

So not sure what I could recommend you, as I don't think we should
change the sd-bus behaviour to anything you'd like...

One option of course would be to do the equivalent of
setresuid(geteuid(), geteuid(), geteuid()); in your app after forking
but before you exec systemctl. Or, even better, just do the bus call
directly from your app, and rely on PK permitting access for
unprivileged clients.

Lennart

-- 
Lennart Poettering, Red Hat
___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] euid 0 not honored authenticating control socket?

2016-01-25 Thread Simon McVittie
On 21/01/16 18:12, Charles Duffy wrote:
> I have a setuid-root executable

... and now you have two problems? :-)

setuid executables are inherently dangerous: they run with one set of
privileges (their euid), but their environment variables, resource
limits, inherited file descriptors, etc. are controlled by a different,
usually lower set of privileges (their real uid). Every piece of code
run in this rather precarious situation needs to be designed to distrust
things that normal application code can safely trust.

Executables that are not specifically designed to be run under setuid
(including systemctl), and libraries that are not specifically designed
to be setuid-safe, should not be run while setuid.

If you are completely confident that your setuid executable has
sanitized its environment - most importantly, cleaning the environment
via a whitelist, like
 does -
then you can set the real and effective uids to the same value,
effectively taking responsibility for dealing with the security boundary.

-- 
Simon McVittie
Collabora Ltd. 

___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel


Re: [systemd-devel] euid 0 not honored authenticating control socket?

2016-01-21 Thread Aaron_Wright
> From: Charles Duffy <char...@dyfis.net>
> To: "systemd-devel@lists.freedesktop.org"  de...@lists.freedesktop.org>
> Date: 01/21/2016 10:12 AM
> Subject: [systemd-devel] euid 0 not honored authenticating control 
socket?
> Sent by: "systemd-devel" <systemd-devel-boun...@lists.freedesktop.org>
> 
> Howdy --
> 
> I have a setuid-root executable from which I'm trying to start or 
> stop a service. However, when invoking systemctl from this 
> executable -- for which geteuid() returns 0 -- the control socket is
> rejected when the ruid does not match (such that the executable was 
> invoked from a less-privileged user).
> 
> 
> 
> What's going on, and why?

Check my thread with a similar question: 
http://lists.freedesktop.org/archives/systemd-devel/2015-May/032444.html___
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel