]> git.ipfire.org Git - thirdparty/dbus.git/commitdiff
dbus-daemon, dbus-launch: cope with callers having closed standard fds
authorSimon McVittie <smcv@debian.org>
Thu, 21 Jul 2016 07:24:38 +0000 (08:24 +0100)
committerSimon McVittie <smcv@debian.org>
Fri, 12 Aug 2016 09:58:38 +0000 (10:58 +0100)
In Debian bug <https://bugs.debian.org/829348>, lightdm appears to
have been starting dbus-launch with at least one of the three
standard fds 0, 1, 2 (stdin, stdout, stderr) closed. This resulted
in the dbus-daemon's epoll_create1() returning a fd less than 3.
Later, _dbus_become_daemon() replaces fds 0-2 with /dev/null. As a
result, a subsequent call to _dbus_loop_add_watch() for the reload
pipe resulted in calling epoll_ctl on the non-epoll fd pointing to
/dev/null, which fails with EINVAL, resulting in the dbus-daemon
exiting unsuccessfully.

Unix programs are not normally expected to behave correctly when
launched with the standard fds not already open; but at the same time,
X11 autolaunching means that dbus-launch (and hence the dbus-daemon)
can get started from an arbitrarily precarious situation.

Bug: https://bugs.freedesktop.org/show_bug.cgi?id=97008
Signed-off-by: Simon McVittie <smcv@debian.org>
Reviewed-by: Thiago Macieira <thiago@kde.org>
(cherry picked from commit c8f73a2a3a9d9d10587f596a62ebb64e8963197e)

bus/main.c
tools/dbus-launch.c

index ee5e1ebff7fc7c72fe3b0c0d78baef419f3524c9..c38f252502b9e9755bb0cf400a88df56fcd0a32f 100644 (file)
 #include "apparmor.h"
 #include "audit.h"
 
+#ifdef DBUS_UNIX
+#include <dbus/dbus-sysdeps-unix.h>
+#endif
+
 static BusContext *context;
 
 #ifdef DBUS_UNIX
@@ -378,6 +382,27 @@ main (int argc, char **argv)
   dbus_bool_t print_address;
   dbus_bool_t print_pid;
   BusContextFlags flags;
+#ifdef DBUS_UNIX
+  const char *error_str;
+
+  /* Redirect stdin from /dev/null since we will never need it, and
+   * redirect stdout and stderr to /dev/null if not already open.
+   *
+   * We should do this as the very first thing, to ensure that when we
+   * create other file descriptors (for example for epoll, inotify or
+   * a socket), they never get assigned as fd 0, 1 or 2. If they were,
+   * which could happen if our caller had (incorrectly) closed those
+   * standard fds, they'd get closed when we daemonize - for example,
+   * closing our listening socket would stop us listening, and closing
+   * a Linux epoll socket would cause the main loop to fail. */
+  if (!_dbus_ensure_standard_fds (DBUS_FORCE_STDIN_NULL, &error_str))
+    {
+      fprintf (stderr,
+               "dbus-daemon: fatal error setting up standard fds: %s: %s\n",
+               error_str, _dbus_strerror (errno));
+      return 1;
+    }
+#endif
 
   if (!_dbus_string_init (&config_file))
     return 1;
index 0f1e6eded8aa24ff009f4f8c3b03fb0677976b09..80e4a2415ceaaea95aca88dec4a9e6ff24ad4df7 100644 (file)
@@ -842,10 +842,25 @@ main (int argc, char **argv)
   char *config_file;
   dbus_bool_t user_bus_supported = FALSE;
   DBusString user_bus;
-  
+  const char *error_str;
+
   exit_with_session = FALSE;
   config_file = NULL;
-  
+
+  /* Ensure that the first three fds are open, to ensure that when we
+   * create other file descriptors (for example for epoll, inotify or
+   * a socket), they never get assigned as fd 0, 1 or 2. If they were,
+   * which could happen if our caller had (incorrectly) closed those
+   * standard fds, then we'd start dbus-daemon with those fds closed,
+   * which is unexpected and could cause it to misbehave. */
+  if (!_dbus_ensure_standard_fds (0, &error_str))
+    {
+      fprintf (stderr,
+               "dbus-launch: fatal error setting up standard fds: %s: %s\n",
+               error_str, _dbus_strerror (errno));
+      return 1;
+    }
+
   prev_arg = NULL;
   i = 1;
   while (i < argc)