On Wed, 2014-07-16 at 16:51 +0200, José Bollo wrote:
> On mer, 2014-07-16 at 13:53 +0200, Patrick Ohly wrote:
> > What I have in mind for option 2 is an extension of the <allow/deny>
> > rules with a <check privilege="foobar"> rule. This <check> rule would
> > have the same match criteria as the <allow/deny> rules. If it matches, a
> > call to cynara with
> >       * client = Smack label of D-Bus client
> >       * user = UID of the client process
> >       * session_id = unique connection name (1)
> >       * privilege = "foobar"
> > determines whether the rule grants access. Note that in this model,
> > Cynara would never be used to take away access already granted before by
> > some other rule. This means that if the current state is "allowed" when
> > evaluating a check rule, it gets skipped, because a "DENIED" would be
> > ignored and an "OKAY" wouldn't change the state.
> > 
> > Alternatively, one could always call Cynara and change the state
> > accordingly, including a transition from "allowed" to "denied". I find
> > that model a bit harder to understand and it would be less efficient
> > (more Cynara checks); if it turns out to be needed, then changing the
> > implementation would be trivial.
> > 
> > (1) As I said before, I have my concerns about such an ad-hoc choice for
> > the session_id. I'd prefer to have a system-wide policy for computing
> > the session_id that matches how the user perceives the life time of an
> > application.
> 
> There a need to define what is THE DEFAULT SESSIONID. I'm not sure that
> the unique DBUS connection name is reliable.

We don't even know what "application session" means, so it is a bit hard
to derive an ID for it.

> > Filtering
> > =========
> > 
> > With rules as outlined above, we can filter by source, destination,
> > interface and member. Filtering by interface and member will be
> > problematic in KDBus because they are part of the opaque payload that
> > KDBus knows nothing about. When relying on these message attributes for
> > filtering, a different approach will be needed if and/or when the
> > services switches to KDBus.
> > 
> > Right now it looks like KDBus will not be a drop-in replacement anyway
> > and is unlikely to be in Tizen 3.0, so this shouldn't prevent us from
> > extending user-space routing via dbus-daemon. Canonical is also moving
> > ahead with their AppArmor patches for dbus-daemon.
> > 
> > There is a comment in the D-Bus man page about deny rules that says:
> >         
> >         send_destination and receive_sender rules mean that messages may 
> > not be sent to or received from the
> >         *owner* of the given name, not that they may not be sent *to that 
> > name*. That is, if a connection owns
> >         services A, B, C, and sending to A is denied, sending to B or C 
> > will not work either.
> > 
> > This also applies to allow rules. What that means is that all well-known
> > names in rules and messages get resolved to the bus name before
> > comparison. If a client is granted the right to send a message to
> > org.example.service1 currently owned by client :1.10, then it is also
> > allowed to send to that client using the name org.example.service2, if
> > that name is also owned by the service.
> > 
> > In practice this is not a problem, because we can and should always
> > include at least the interface in rules.
> 
> Does this last point contradict what you said about KDBUS? In my humble
> understanding yes.

I was talking about the current work with dbus-daemon here. In that case
we can rely on the interfaces as criteria.

As KDBus looks like it will require service changes, that's the point in
time when we need to worry about securing them. I consider that out of
scope at the moment.

> > Broadcasts
> > ==========
> > 
> > Broadcasting confidential information is problematic, as explained in my
> > comment on AMB's security requirements. A D-Bus service cannot control
> > which clients receive a signal unless it explicitly specifies only a
> > single recipient. In the current D-Bus subscriber model, this is not
> > possible because the service doesn't even get to know who is interested.
> > 
> > The dbus-daemon can route signals more selectively only to privileged
> > recipients. However, the rule matching cannot filter by message content.
> > The popular PropertyChanged signal cannot be filtered selectively.
> > 
> > This is only relevant if these signals are part of the API which we want
> > exposed to less-privileged clients. For privileged clients the default
> > allow rule would still let the signal through.
> 
> If, by the cynara meaning, an unauthorized client can subscribe to
> messages that it should not receive and receive them then there is a
> hole in the security. Is it what you write?

No. By default, signals are never delivered to less-privileged clients.
What I am saying is that we can only open up access with privilege
checks to some kind of signals.

There are classes of signals (for example, PropertyChanged) were the
privilege check would have to be made by some criteria other than those
known to dbus-daemon. In those cases I don't see any solution other than
modifying the services: either it needs to change the API or send the
same signal multiple times, once to each recipient (but even that is
probably depending on an API change, because the traditional D-Bus watch
model does not inform the service about subscribed clients).

I think we can enable signals explicitly sent to a certain client
(untested, though).


> > Specific dbus-daemon behavior
> > =============================
> > 
> > dbus-daemon evaluates policy rules in bus_client_policy_check_can_send()
> > and bus_client_policy_check_can_receive().
> > 
> > Both methods are supposed to return a response immediately without
> > blocking. My current thinking is that they must be extended to return a
> > "don't know yet" result. This must abort processing for the time being,
> > just like an out-of-memory error would. How this works for each call
> > chain varies.
> > 
> > For can_send it affects the processing of the data coming from a
> > specific client. This data queue can be frozen while waiting for a
> > response from Cynara. This is an advantage over handling the Cynara
> > check in the recipient, because it prevents a malicious or broken client
> > from sending further messages while its previous message gets considered.
> > 
> > can_receive is more difficult. We don't want to block the sender,
> > because it might have to service other clients. So we may have to
> > tentatively accept the message for the recipient, block the queue
> > delivering data to it and then later repeat the receive check.
> > 
> > This can cause messages to pile up inside dbus-daemon, in particular
> > when we apply this to broadcasts. This behavior can also already be 
> > observed in
> > normal D-Bus when a client subscribes to a signal and the stops reading
> > the data: memory consumption in dbus-daemon keeps going up until it
> > eventually hits the per-client memory limit (rather large though!) and
> > drops messages.
> 
> Is it blocking the DBUS daemon?

No. It keeps allocating more memory as the queue of the slow client
keeps growing. You can test that with dbus-send and dbus-monitor:

while DBUS_SESSION_BUS_ADDRESS=$addr dbus-send
--type=signal /org/freedesktop/sample/object/name
org.freedesktop.ExampleInterface.ExampleSignal int32:47 string:'hello
world' double:65.32 array:string:"1st item","next item","last item"
dict:string:int32 "one",1,"two",2,"three",3  variant:int32:-8
objpath:/org/freedesktop/sample/object/name; do true; done &
DBUS_SESSION_BUS_ADDRESS=$addr dbus-monitor >/dev/null &
DBUS_SESSION_BUS_ADDRESS=$addr dbus-monitor >/dev/null
<CTRL-Z>

This stops the second dbus-monitor. You can then watch with top how the
memory footprint of dbus-daemon grows. I also noticed that it doesn't go
back down when that second dbus-monitor disconnects.

> > Handling rejections and user interaction
> > ========================================
> > 
> > At the moment, dbus-daemon generates a
> > org.freedesktop.DBus.Error.AccessDenied error reply when a method call
> > gets rejected by the daemon. This is somewhat cryptic:
> > $ dbus-send --print-reply --dest=org.example.service1 /example/path 
> > org.example.Echo.SayHello
> > Error org.freedesktop.DBus.Error.AccessDenied: Rejected send message, 1 
> > matched rules; type="method_call", sender=":1.8" (uid=1001 pid=13960 
> > comm="dbus-send --print-reply --dest=org.example.service") 
> > interface="org.example.Echo" member="SayHello" error name="(unset)" 
> > requested_reply="0" destination="org.example.service1" (uid=57618 pid=13950 
> > comm="/usr/bin/python /work/dbus/service.py ")
> > 
> > It includes information about the destination (uid, pid, comm) that we
> > might not want leaked to the caller (?).
> > 
> > It would be nicer if the AccessDenied error contained information about
> > all failed Cynara privilege checks, because then the app developer would
> > know what he needs to request in the manifest.
> 
> Agreed. But is it possible?

I think it is. The code which currently only counts the matched rules
would have to be extended to also track the checked Cynara privileges.

-- 
Best Regards, Patrick Ohly

The content of this message is my personal opinion only and although
I am an employee of Intel, the statements I make here in no way
represent Intel's position on the issue, nor am I authorized to speak
on behalf of Intel on this matter.



_______________________________________________
Dev mailing list
Dev@lists.tizen.org
https://lists.tizen.org/listinfo/dev

Reply via email to