[systemd-devel] SD_BUS_VTABLE_CAPABILITY

Andy Lutomirski luto at amacapital.net
Thu Apr 16 12:30:28 PDT 2015


On Thu, Apr 16, 2015 at 11:23 AM, Lennart Poettering
<lennart at poettering.net> wrote:
> On Thu, 16.04.15 10:52, Andy Lutomirski (luto at amacapital.net) wrote:
>
>> >
>> > It would be very helpful if you could go into details on why you think
>> > more care is needed here than for other things. Is there anything
>> > non-trivial going on here that I'm missing? The way capabilites are
>> > exposed through kdbus seems perfectly straight-forward to me, so I'm
>> > really trying to get my head around your concerns here.
>> >
>> > So, let me ask explicitly again:
>> >
>> >     * Are there any actual exploitable vulnerabilities you are aware
>> > of in the kdbus kernel code?
>> >
>> >     * Are there any actual exploitable vulnerabilities on the sd-bus
>> > userspace code you are aware of, regardless if in the kdbus or dbus1
>> > support in it?
>> >
>> > If you are, please provide us with good explanations, so that we can
>> > do something about them. We'd love to fix this!
>>
>> I don't see a vulnerability in the code as such.  But you still
>> haven't given a real use case, and vulnerabilities in security
>> mechanisms are often found in the interactions between components.
>> There doesn't seem to be a big picture here.
>>
>> Can you give a plausible real world example along the lines of
>> "process A, which has capability B for some decent reason, will send
>> message C to daemon D, and D will permit the request because of
>> capability B, but the request would not otherwise have been
>> permitted."
>>
>> So far it seems like there's a bunch of code that may not be
>> exploitable but doesn't really do anything either.
>>
>> And, honestly, if this is only about rebooting and setting the time,
>> then, even if correct, this is seriously not worth the complexity even
>> if it's completely sensible and correct.
>
> Well, you asked for examples, I gave you two simple, existing
> ones.
>
> Note that the caps-based method authorization is not much used
> currently, especially not outside of systemd, because it's not safely
> doable on dbus1, but only on kdbus, and kdbus is not merged into the
> kernel yet, hence not many projects use it yet.
>
> But anyway, here are two more example in systemd itself:
>
> systemd itself checks CAP_SYS_KILL for clients asking to kill
> arbitrary services (which means invoking kill() to all PIDs in the
> service's cgroup).
>
> Similar to this, logind checks CAP_SYS_KILL for clients asking to kill
> sessions (which means invoking kill() for all PIDS in the session).
>

These aren't the kinds of examples I'm asking about.  They're what
systemd does, not what use case makes doing that serve a purpose..

> Now, to put together a more complex scenario for you: consider a small
> web UI that can be used to set the system time. It should realy run at
> minimal privileges, after all it has a surface to the web. Hence you
> write it as daemon, make it run as a user id of its own, set up a
> chroot() or a file system namespace, but you do keep CAP_SYS_TIME and
> a bus connection open.

Aha, a real example!

But this is a bad example -- systemd should provide the web server
with a way to retain the right to issue the one method call that it
needs.  CAP_SYS_TIME is overbroad.  For example, CAP_SYS_TIME also
grants the service to bypass whatever auditing and logging systemd
would do.

And this is also a worthless design pattern, as it seems to be
applicable to sending signals and changing the time, and probably very
little else.

> With that setup the web daemon can pretty much
> only set the system clock, and if it exploited cannot be used for much
> else. It will not have access to /dev/rtc, due to the file system
> namespace, but it can nicely set the system clock via timedated still,
> and pretty much only that, and the clock will be synced to the RTC by
> it.

It can set the time with settimeofday(2), which is undesirable.

>
> To map this back to your earlier request for an example. In this case
> process A is the web UI daemon. Capability B is CAP_SYS_TIME. Message
> C is the SetTime() bus call. Daemon D is timedated.
>
> If the web UI daemon would not have CAP_SYS_TIME it couldn't change
> the time like this -- unless of course that web UI daemon would run as
> UID 0 all the time, which is certainly much much less desirable, given
> that it is a network facing daemon.
>
> And if you are not happy with this example, there are numerous others
> like this of course...

Honestly, I doubt that.  There are a smallish number of capabilities
and a much smaller number that make sense in this manner.

Here's what I think is going on: if I propose a kernel patch to change
the kernel to let my app do such-and-such, and I convince everyone
involved that the patch is bug-free, maintainable, cleanly written,
secure, etc, that's still not enough justification to merge it,
especially if it's an ABI change.  I also need to justify why it's a
good idea for my app to do whatever I'm enabling and why the kernel
should support it in that way.

AFAICT this piece of kdbus code serves to enable a rather odd way to
write privilege-separated services to change the time and kill
processes.  The cost is complex security code that, at best, fails
secure in the presence of different user namespaces, and the cost also
involves touching a global refcount for each message sent (this might
be the *only* thing that would reference init_user_ns's refcount when
sending).  Oh yeah, the cost is also ABI crap -- if, say, my
cap_ambient stuff gets merged, then either someone needs to decide
that kdbus shouldn't support it or someone should figure out how kdbus
would support it.  And the current examples are apparently useless
garbage like cap_permitted, cap_inheritable, and the bounding set.

The cost here really doesn't seem to justify the benefit.

And don't even get me started on cmdline.

--Andy


More information about the systemd-devel mailing list