Sophie

Sophie

distrib > Mageia > 3 > x86_64 > by-pkgid > 9bd6c61b93a77b33aa5c068cb9529372 > files > 6

dbus-1.6.8-4.5.mga3.src.rpm

From 68c1c8141c9f83af157dcf358e388f424cc4e0a4 Mon Sep 17 00:00:00 2001
From: Simon McVittie <simon.mcvittie@collabora.co.uk>
Date: Fri, 12 Sep 2014 16:06:42 +0100
Subject: [PATCH 02/11] config: change DEFAULT_MESSAGE_UNIX_FDS to 16

Based on a patch by Alban Crequy. Now that it's the same on all
platforms, there's little point in it being set by configure/cmake.

This change fixes two distinct denials of service:

fd.o#82820, part A
------------------

Before this patch, the system bus had the following default configuration:
- max_connections_per_user: 256
- DBUS_DEFAULT_MESSAGE_UNIX_FDS: usually 1024 (or 256 on QNX, see fd.o#61176)
  as defined by configure.ac
- max_incoming_unix_fds: DBUS_DEFAULT_MESSAGE_UNIX_FDS*4 = usually 4096
- max_outgoing_unix_fds: DBUS_DEFAULT_MESSAGE_UNIX_FDS*4 = usually 4096
- max_message_unix_fds: DBUS_DEFAULT_MESSAGE_UNIX_FDS = usually 1024

This means that a single user could create 256 connections and transmit
256*4096 = 1048576 file descriptors.

The file descriptors stay attached to the dbus-daemon process while they are
in the message loader, in the outgoing queue or waiting to be dispatched before
D-Bus activation.

dbus-daemon is usually limited to 65536 file descriptors (ulimit -n). If the
limit is reached and dbus-daemon needs to receive a message with a file
descriptor attached, this is signalled by recvfrom with the flag MSG_CTRUNC.
Dbus-daemon cannot recover from that error because the kernel does not have any
API to retrieve a file descriptor which has been discarded with MSG_CTRUNC.
Therefore, it closes the connection of the sender. This is not necessarily the
connection which generated the most file descriptors so it can lead to
denial-of-service attacks.

In order to prevent DoS issues, this patch reduces DEFAULT_MESSAGE_UNIX_FDS to
16:

max_connections_per_user * max_incoming_unix_fds = 256 * 64 = 16384

This is less than the usual "ulimit -n" (65536) with a good margin to
accomodate the other sources of file descriptors (stdin/stdout/stderr,
listening sockets, message loader, etc.).

Distributors on non-Linux may need to configure a smaller limit in
system.conf, if their limit on the number of fds is smaller than
Linux's.

fd.o#82820, part B
------------------

On Linux, it's not possible to send more than 253 fds in a single sendmsg()
call: sendmsg() would return -EINVAL.
  #define SCM_MAX_FD      253

SCM_MAX_FD changed value during Linux history:
- it used to be (OPEN_MAX-1)
- commit c09edd6eb (Jul 2007) changed it to 255
- commit bba14de98 (Nov 2010) changed it to 253

Libdbus always sends all of a message's fds, and the beginning
of the message itself, in a single sendmsg() call. Combining these
two, a malicious sender could split a message across two or more
sendmsg() calls to construct a composite message with 254 or more
fds. When dbus-daemon attempted to relay that message to its
recipient in a single sendmsg() call, it would receive EINVAL,
interpret that as a fatal socket error and disconnect the recipient,
resulting in denial of service.

This is fixed by keeping max_message_unix_fds <= SCM_MAX_FD.

Bug: https://bugs.freedesktop.org/show_bug.cgi?id=82820
---
 bus/config-parser.c | 6 +++---
 bus/session.conf.in | 3 ++-
 dbus/dbus-message.c | 3 ++-
 dbus/dbus-sysdeps.h | 8 ++++++++
 4 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/bus/config-parser.c b/bus/config-parser.c
index e4a0262..cc29ef4 100644
--- a/bus/config-parser.c
+++ b/bus/config-parser.c
@@ -413,9 +413,9 @@ bus_config_parser_new (const DBusString      *basedir,
       maximum number of file descriptors we can receive. Picking a
       high value here thus translates directly to more memory
       allocation. */
-      parser->limits.max_incoming_unix_fds = 1024*4;
-      parser->limits.max_outgoing_unix_fds = 1024*4;
-      parser->limits.max_message_unix_fds = 1024;
+      parser->limits.max_incoming_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS*4;
+      parser->limits.max_outgoing_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS*4;
+      parser->limits.max_message_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS;
       
       /* Making this long means the user has to wait longer for an error
        * message if something screws up, but making it too short means
diff --git a/bus/session.conf.in b/bus/session.conf.in
index e121ff9..6ce8503 100644
--- a/bus/session.conf.in
+++ b/bus/session.conf.in
@@ -49,7 +49,8 @@
   <limit name="max_outgoing_bytes">1000000000</limit>
   <limit name="max_outgoing_unix_fds">250000000</limit>
   <limit name="max_message_size">1000000000</limit>
-  <limit name="max_message_unix_fds">4096</limit>
+  <!-- We do not override max_message_unix_fds here since the in-kernel
+       limit is also relatively low -->
   <limit name="service_start_timeout">120000</limit>  
   <limit name="auth_timeout">240000</limit>
   <limit name="max_completed_connections">100000</limit>  
diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c
index fc61ae7..b0c641e 100644
--- a/dbus/dbus-message.c
+++ b/dbus/dbus-message.c
@@ -35,6 +35,7 @@
 #include "dbus-list.h"
 #include "dbus-threads-internal.h"
 #ifdef HAVE_UNIX_FD_PASSING
+#include "dbus-sysdeps.h"
 #include "dbus-sysdeps-unix.h"
 #endif
 
@@ -3802,7 +3803,7 @@ _dbus_message_loader_new (void)
   SCM_RIGHTS works we need to preallocate an fd array of the maximum
   number of unix fds we want to receive in advance. A
   try-and-reallocate loop is not possible. */
-  loader->max_message_unix_fds = 1024;
+  loader->max_message_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS;
 
   if (!_dbus_string_init (&loader->data))
     {
diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h
index df4c5e0..64b6363 100644
--- a/dbus/dbus-sysdeps.h
+++ b/dbus/dbus-sysdeps.h
@@ -537,6 +537,14 @@ void _dbus_request_file_descriptor_limit (unsigned int limit);
 const char *
 _dbus_replace_install_prefix (const char *configure_time_path);
 
+/* Do not set this too high: it is a denial-of-service risk.
+ * See <https://bugs.freedesktop.org/show_bug.cgi?id=82820>
+ *
+ * (This needs to be in the non-Unix-specific header so that
+ * the config-parser can use it.)
+ */
+#define DBUS_DEFAULT_MESSAGE_UNIX_FDS 16
+
 /** @} */
 
 DBUS_END_DECLS
-- 
2.1.0