Make uid 0 immune to pending_fd_timeout limit
authorSimon McVittie <simon.mcvittie@collabora.co.uk>
Fri, 11 Nov 2016 16:40:44 +0000 (16:40 +0000)
committerSimon McVittie <simon.mcvittie@collabora.co.uk>
Fri, 11 Nov 2016 16:40:44 +0000 (16:40 +0000)
This is a workaround for
<https://bugs.freedesktop.org/show_bug.cgi?id=95263>. If a service
sends a file descriptor sufficiently frequently that its queue of
messages never goes down to 0 fds pending, then it will eventually be
disconnected. logind is one such service.

We do not currently have a good solution for this: the proposed
patches either don't work, or reintroduce a denial of service
security vulnerability (CVE-2014-3637). Neither seems desirable.
However, we can avoid the worst symptoms by trusting uid 0 not to be
malicious.

Bug: https://bugs.freedesktop.org/show_bug.cgi?id=95263
Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/1591411
Reviewed-by: Ɓukasz Zemczak
Tested-by: Ivan Kozik
Tested-by: Finn Herpich
Tested-by: autostatic
Tested-by: Ben Parafina
Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
bus/connection.c
test/dbus-daemon.c

index bdb2fea..58fc219 100644 (file)
@@ -702,10 +702,24 @@ pending_unix_fds_timeout_cb (void *data)
 {
   DBusConnection *connection = data;
   BusConnectionData *d = BUS_CONNECTION_DATA (connection);
+  unsigned long uid;
   int limit;
 
   _dbus_assert (d != NULL);
   limit = bus_context_get_pending_fd_timeout (d->connections->context);
+
+  if (dbus_connection_get_unix_user (connection, &uid) && uid == 0)
+    {
+      bus_context_log (d->connections->context, DBUS_SYSTEM_LOG_WARNING,
+                       "Connection \"%s\" (%s) has had Unix fds pending for "
+                       "too long (pending_fd_timeout=%dms); tolerating it, "
+                       "because it has uid 0",
+                       d->name != NULL ? d->name : "(null)",
+                       bus_connection_get_loginfo (connection),
+                       limit);
+      return TRUE;
+    }
+
   bus_context_log (d->connections->context, DBUS_SYSTEM_LOG_WARNING,
       "Connection \"%s\" (%s) has had Unix fds pending for too long, "
       "closing it (pending_fd_timeout=%d ms)",
index 44b3dfb..ba67f43 100644 (file)
@@ -997,6 +997,12 @@ test_pending_fd_timeout (Fixture *f,
   if (f->skip)
     return;
 
+  if (getuid () == 0)
+    {
+      g_test_skip ("Cannot test, uid 0 is immune to this limit");
+      return;
+    }
+
   have_mem = dbus_connection_add_filter (f->left_conn, wait_for_disconnected_cb,
       &disconnected, NULL);
   g_assert (have_mem);