Bug 52372 - dbus-daemon drops messages if sender exits during service activation
Summary: dbus-daemon drops messages if sender exits during service activation
Status: RESOLVED MOVED
Alias: None
Product: dbus
Classification: Unclassified
Component: core (show other bugs)
Version: 1.5
Hardware: All All
: medium normal
Assignee: D-Bus Maintainers
QA Contact: D-Bus Maintainers
URL:
Whiteboard:
Keywords:
: 36125 (view as bug list)
Depends on: 896
Blocks:
  Show dependency treegraph
 
Reported: 2012-07-22 21:49 UTC by Kerrick Staley
Modified: 2018-10-12 21:14 UTC (History)
6 users (show)

See Also:
i915 platform:
i915 features:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Kerrick Staley 2012-07-22 21:49:16 UTC
If you pass the --print-reply flag to dbus-send, it results in a "method call". Without the flag, it sends a "signal". The dbus-send manpage says

--print-reply
      Block for a reply to the message sent, and print any reply received in a human-readable form.

so it seems that --print-reply should only change the output of dbus-send (similar to a --verbose flag).


I encountered this bug because the command

dbus-send --dest=org.gnome.Shell /org/gnome/Shell org.freedesktop.DBus.Properties.Set string:org.gnome.Shell string:OverviewActive variant:boolean:true

has no effect unless you pass the --print-reply flag.


This bug is in dbus 1.6.4, but the "Version" field of the bug report doesn't contain that option (it only goes up to 1.5).
Comment 1 Simon McVittie 2013-01-24 17:08:14 UTC
(dbus/doc is a dead project; documentation of things that live in dbus.git is dbus/core. Reassigning.)

Does --type=method_call, without --print-reply, also do what you want?

The reason for the change in behaviour is that the default message type is signal, not method call; signals don't have a reply, so --print-reply only makes sense for method calls, so it changes the default type.

Documentation patches welcome.

There was a bug in the past in which dbus-send without --print-reply also didn't flush the socket, leading to the message not actually being sent. I believe that was fixed a while ago, though.
Comment 2 Robin Stocker 2013-05-19 12:36:36 UTC
(In reply to comment #1)
> There was a bug in the past in which dbus-send without --print-reply also
> didn't flush the socket, leading to the message not actually being sent. I
> believe that was fixed a while ago, though.

I have a case where --print-reply seems to work reliably:

dbus-send --print-reply --dest=org.freedesktop.FileManager1 /org/freedesktop/FileManager1 org.freedesktop.FileManager1.ShowItems array:string:"file:///home" string:test

But with the following, it seems to fail 1 out of every 3 times:

dbus-send --type=method_call --dest=org.freedesktop.FileManager1 /org/freedesktop/FileManager1 org.freedesktop.FileManager1.ShowItems array:string:"file:///home" string:test

`dbus-send --version` does not return the version, but according to yum, "dbus" is version 1.6.8. Is that a version which should include the above mentioned fix?
Comment 3 Simon McVittie 2013-05-20 10:21:17 UTC
(In reply to comment #2)
> `dbus-send --version` does not return the version, but according to yum,
> "dbus" is version 1.6.8. Is that a version which should include the above
> mentioned fix?

Yes, it was back in 2009. Looks like that fix was not complete, then :-(

Best-practice is to use --print-reply when calling methods with dbus-send (or use "gdbus call", or "qdbus", or something other than shell script): otherwise, if it fails, you can never know.

Documentation patches to clarify this would be very welcome, preferably against git master or a 1.7.x development release, in which the source code for the documentation has changed from doc/dbus-send.1 (troff format) to doc/dbus-send.1.xml.in (Docbook XML).
Comment 4 Simon McVittie 2013-06-05 16:39:34 UTC
(In reply to comment #0)
> If you pass the --print-reply flag to dbus-send, it results in a "method
> call". Without the flag, it sends a "signal". The dbus-send manpage says
> 
> --print-reply
>       Block for a reply to the message sent, and print any reply received in
> a human-readable form.

Chengwei Yang has documented this. It'll be in 1.7.4.

(In reply to comment #2)
> I have a case where --print-reply seems to work reliably:
> 
> dbus-send --print-reply --dest=org.freedesktop.FileManager1
> /org/freedesktop/FileManager1 org.freedesktop.FileManager1.ShowItems
> array:string:"file:///home" string:test
> 
> But with the following, it seems to fail 1 out of every 3 times:
> 
> dbus-send --type=method_call --dest=org.freedesktop.FileManager1
> /org/freedesktop/FileManager1 org.freedesktop.FileManager1.ShowItems
> array:string:"file:///home" string:test

This is still a bug.
Comment 5 Nelson Benitez 2013-09-04 00:12:55 UTC
I also hit this bug while testing the org.freedesktop.FileManager1 interface with dbus-send, very confusing that it does not work without the "--print-reply" option.
Comment 6 Chengwei Yang 2013-11-08 03:35:27 UTC
This is a some kind of issue related time race condition, if we close the connection immediately, the daemon will cancel later operations, in the FileManager1 case, it's spawning naultilus.

It's simple to verify/workaround this issue, just sleep several (e.g. 3) seconds after dbus_connection_flush().

I'm not considering this is a dbus-send bug, it just do what it should do, send the message without wait for reply (without --print-reply).

Simon, do you consider this is a dbus-daemon bug? Which in fact from my point of view, shouldn't cancel operations in this case (non-block nor wait for reply).
Comment 7 Simon McVittie 2013-11-08 12:17:32 UTC
Are you saying the bug is something like this?

* dbus-send sends a message M to dbus-daemon
* dbus-send closes its connection to dbus-daemon
* race condition: if dbus-daemon notices the connection closure (or
  some similar condition) before it processes M, then it will not
  process M at all

If so, then I'd say that's a dbus-daemon bug.
Comment 8 Chengwei Yang 2013-11-08 14:09:31 UTC
(In reply to comment #7)
> Are you saying the bug is something like this?
> 
> * dbus-send sends a message M to dbus-daemon
> * dbus-send closes its connection to dbus-daemon
> * race condition: if dbus-daemon notices the connection closure (or
>   some similar condition) before it processes M, then it will not
>   process M at all
> 
> If so, then I'd say that's a dbus-daemon bug.

Yes, so far I haven't dive into that part of code, I'll check later.
Comment 9 Chengwei Yang 2013-12-06 08:35:39 UTC
See #bug36125 for a more details bug report. I add a debug _dbus_warn() to the code path. The test on fedora 19 like below.

1. start a new session bus, so no other services activated except the org.freedesktop.DBus.

[chengwei@vm-fedora-19 dbus.git]$ ./tmp_install/bin/dbus-daemon --print-pid= --print-address= --session                                     
unix:abstract=/tmp/dbus-n1JKFTryQ6,guid=51c3b039436e37fa0d8d549352a186b7
1975

2. run dbus-send to send a message to org.freedesktop.FileManager1 like below.

[chengwei@vm-fedora-19 dbus.git]$ ./tools/dbus-send --type=method_call --dest=org.freedesktop.FileManager1 /org/freedesktop/FileManager1 org.freedesktop.FileManager1.ShowItems array:string:"file:///home" string:test

3. the dbus-daemon output like below

Activating service name='org.freedesktop.FileManager1'
Activating service name='org.gtk.vfs.Daemon'
Successfully activated service 'org.gtk.vfs.Daemon'
Activating service name='org.gtk.Private.UDisks2VolumeMonitor'
Successfully activated service 'org.gtk.Private.UDisks2VolumeMonitor'
Activating service name='org.gtk.Private.GPhoto2VolumeMonitor'
Successfully activated service 'org.gtk.Private.GPhoto2VolumeMonitor'
Activating service name='org.gtk.Private.MTPVolumeMonitor'
Successfully activated service 'org.gtk.Private.MTPVolumeMonitor'
Activating service name='org.gtk.Private.AfcVolumeMonitor'
Successfully activated service 'org.gtk.Private.AfcVolumeMonitor'
Activating service name='org.gtk.Private.GoaVolumeMonitor'
Activating service name='org.gnome.OnlineAccounts'
Successfully activated service 'org.gnome.OnlineAccounts'
Successfully activated service 'org.gtk.Private.GoaVolumeMonitor'
Successfully activated service 'org.freedesktop.FileManager1'
oops, the client which send activate message to the service is gone

4. repeat step 2 again, dbus-daemon output below 3 lines more.

Activating service name='org.freedesktop.FileManager1'
Successfully activated service 'org.freedesktop.FileManager1'
oops, the client which send activate message to the service is gone


Conclusion:

FileManager1 isn't a daemon or isn't running in daemon mode, I know generally nothing about it. :-(. So it will be activated everytime.

Yes, dbus-daemon does check the client connection before dispatch the pending activate message to the started service. And it will remove the leftover message when removing the pending activation.

As desrt said in #bug36125

> This makes sense for a couple of reasons:
> 
>  - if the sender is no longer existing, then they don't care about it anymore
> 
>  - it's weird for a service to receive a message from a non-existent sender

So seems simple removing the check doesn't make sense.

Maybe a solution what I can tell so far is that shall we dispatch a message with "no reply" set?

So in our case, dbus-send message with "no reply" set, that means "hey, message bus, here is the message, I don't care reply at all, so if when you dispatch the message and seeing I'm not here, fine, just go and send it."
Comment 10 Chengwei Yang 2013-12-06 08:37:35 UTC
*** Bug 36125 has been marked as a duplicate of this bug. ***
Comment 11 Simon McVittie 2013-12-06 13:34:21 UTC
(In reply to comment #9)
> Maybe a solution what I can tell so far is that shall we dispatch a message
> with "no reply" set?

I don't like that solution - if "no reply" also meant "this message should have its side-effect even if I exit", that's just as strange as --print-reply also meaning "be more careful that the message actually arrives".

desrt wrote:
> This makes sense for a couple of reasons:
> 
>  - if the sender is no longer existing, then they don't care about it anymore
> 
>  - it's weird for a service to receive a message from a non-existent sender

For the former, I can see points both ways. On one hand, the sender asked for a side-effect, so that side-effect should happen. On the other hand, they can't have cared about it *that* much if they're not handling errors, and they can't handle errors unless they wait for a reply.

For the latter, what would they be doing about the sender? If the answer is "query some sort of information about it" then this race is possible already (ordering events in the dbus-daemon's perception of time):

* sender sends PleaseDoSomething
* [maybe activation happens and time passes here]
* dbus-daemon passes PleaseDoSomething to recipient
* at this point, sender exits
* recipient, or PolicyKit, sends GetConnectionUnixProcessID (or
  something) to dbus-daemon
* dbus-daemon replies "that unique name doesn't exist"

so recipients that want to inspect a sender already have to cope with the sender disappearing.

At the moment I would be inclined to go for "deliver the message anyway", but I could be persuaded to WONTFIX this instead if people have good reasons to consider it "not a bug".

I still stand by what I said in Comment #3, though: if you're using dbus-send to call a method in a shell script, best-practice is to use --print-reply, because otherwise you cannot hope to be able to report errors.

I started to describe the correct semantics for a scriptable dbus-send clone, then realized that the "gdbus call" subcommand in GLib's gdbus tool already implements them:

* call the method and wait for a reply
* if the reply is successful, print the arguments to stdout and exit 0
* if the reply is an error, print it to stderr in the form
  "com.example.ErrorName: could not do what you wanted" and exit 1
Comment 12 Chengwei Yang 2013-12-10 03:25:36 UTC
(In reply to comment #11)
> (In reply to comment #9)
> > Maybe a solution what I can tell so far is that shall we dispatch a message
> > with "no reply" set?
> 
> I don't like that solution - if "no reply" also meant "this message should
> have its side-effect even if I exit", that's just as strange as
> --print-reply also meaning "be more careful that the message actually
> arrives".
> 
> desrt wrote:
> > This makes sense for a couple of reasons:
> > 
> >  - if the sender is no longer existing, then they don't care about it anymore
> > 
> >  - it's weird for a service to receive a message from a non-existent sender
> 
> For the former, I can see points both ways. On one hand, the sender asked
> for a side-effect, so that side-effect should happen. On the other hand,
> they can't have cared about it *that* much if they're not handling errors,
> and they can't handle errors unless they wait for a reply.
> 
> For the latter, what would they be doing about the sender? If the answer is
> "query some sort of information about it" then this race is possible already
> (ordering events in the dbus-daemon's perception of time):
> 
> * sender sends PleaseDoSomething
> * [maybe activation happens and time passes here]
> * dbus-daemon passes PleaseDoSomething to recipient
> * at this point, sender exits
> * recipient, or PolicyKit, sends GetConnectionUnixProcessID (or
>   something) to dbus-daemon
> * dbus-daemon replies "that unique name doesn't exist"

In fact, before that, the message can not pass the bus_context_check_security_policy() check.

I'm also thinking a security hole related this part of code.

Currently,

 * client send message to a service
 * if the service isn't here, then activate it
 * dispatch the activation message to the activated service (security check here)

So in current implementation, we can't prevent service been activated from a denied activation message, because the activation message isn't been checked before we activate the service.

However, not a critical bug to me seems can not be a DoS bug because we don't terminate the activated service in any way.

> 
> so recipients that want to inspect a sender already have to cope with the
> sender disappearing.
> 
> At the moment I would be inclined to go for "deliver the message anyway",
> but I could be persuaded to WONTFIX this instead if people have good reasons
> to consider it "not a bug".
> 
> I still stand by what I said in Comment #3, though: if you're using
> dbus-send to call a method in a shell script, best-practice is to use
> --print-reply, because otherwise you cannot hope to be able to report errors.
> 
> I started to describe the correct semantics for a scriptable dbus-send
> clone, then realized that the "gdbus call" subcommand in GLib's gdbus tool
> already implements them:
> 
> * call the method and wait for a reply
> * if the reply is successful, print the arguments to stdout and exit 0
> * if the reply is an error, print it to stderr in the form
>   "com.example.ErrorName: could not do what you wanted" and exit 1

So you'd prefer a block-wait-for-reply dbus-send for method_call? It's also fine for me to avoid this known issue to do this change.

"--print-reply[=literal]", do not change, block-wait-for-reply, print reply in [literal] format.

"--type=method_call --print-reply[=literal]", do not change, block-wait-for-reply, print reply or error.

"--type=method_call", block-wait-for-reply, do not print reply, exit 0(reply received), 1(error received), this is the only imcompatible change.
Comment 13 Simon McVittie 2014-09-08 13:44:16 UTC
(In reply to comment #12)
> (In reply to comment #11)
> > I started to describe the correct semantics for a scriptable dbus-send
> > clone, then realized that the "gdbus call" subcommand in GLib's gdbus tool
> > already implements them
> 
> So you'd prefer a block-wait-for-reply dbus-send for method_call?

I'd prefer users of dbus-send to use gdbus, if that's the best tool for the job.

> "--type=method_call", block-wait-for-reply, do not print reply, exit 0(reply
> received), 1(error received), this is the only imcompatible change.

Incompatible changes are bad, so if this is an incompatible change, we shouldn't do it (and if that means dbus-send is constrained to be a bad tool by backwards-compat concerns, then we should encourage people to use a better tool).

Looking at codesearch.debian.net, I notice that purple-send-async in libpurple specifically doesn't wait for, or print, the reply, and documents this as a feature; so it seems people want this for some reason. Still no idea whether it has ever been reliable, but that seems like an indication that delivering the messages through dbus-daemon anyway would be better than dropping them on the floor when the sender disconnects.

(In reply to comment #12)
> So in current implementation, we can't prevent service been activated from a
> denied activation message, because the activation message isn't been checked
> before we activate the service.

As noted in the advisory for CVE-2014-3477 (Bug #78979), we don't consider "any process can activate any service, even if it would not subsequently be allowed to send a message to that service" to be a vulnerability.

(In reply to comment #0)
> If you pass the --print-reply flag to dbus-send, it results in a "method
> call". Without the flag, it sends a "signal".

xdg-utils relies on this. On one hand, xdg-utils is pretty much the flagship example of "if you have a non-trivial problem and you solve it with shell scripts, now you have two problems"; on the other hand, it's a (set of) real-world application(s) that would be broken by changing those semantics. So this will not be changed.
Comment 14 GitLab Migration User 2018-10-12 21:14:25 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/dbus/dbus/issues/72.


Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.