Commit cf717118 authored by Simon McVittie's avatar Simon McVittie

Fix several security issues

  - CVE-2014-3635: do not accept an extra fd in cmsg padding,
    avoiding a buffer overrun in dbus-daemon or system services
  - CVE-2014-3636: reduce maximum number of file descriptors
     per message from 1024 to 16, to avoid two separate denial-of-service
     attacks that could cause system services to be dropped from the bus
  - CVE-2014-3637: time out connections that have a
     partially-sent message containing a file descriptor, so that
     malicious processes cannot use self-referential file descriptors
     to make a connection that will never close
  - CVE-2014-3638: reduce maximum number of pending replies
    per connection to avoid algorithmic complexity DoS
  - CVE-2014-3639: reduce timeout for authentication and
    do not accept() new connections when all unauthenticated connection
    slots are in use, so that malicious processes cannot prevent new
    connections to the system bus
parent ad0ee4fc
dbus (1.6.8-1+deb7u4) wheezy-security; urgency=high
* Fix several security issues
- CVE-2014-3635: do not accept an extra fd in cmsg padding,
avoiding a buffer overrun in dbus-daemon or system services
- CVE-2014-3636: reduce maximum number of file descriptors
per message from 1024 to 16, to avoid two separate denial-of-service
attacks that could cause system services to be dropped from the bus
- CVE-2014-3637: time out connections that have a
partially-sent message containing a file descriptor, so that
malicious processes cannot use self-referential file descriptors
to make a connection that will never close
- CVE-2014-3638: reduce maximum number of pending replies
per connection to avoid algorithmic complexity DoS
- CVE-2014-3639: reduce timeout for authentication and
do not accept() new connections when all unauthenticated connection
slots are in use, so that malicious processes cannot prevent new
connections to the system bus
-- Simon McVittie <smcv@debian.org> Mon, 15 Sep 2014 19:48:51 +0100
dbus (1.6.8-1+deb7u3) wheezy-security; urgency=high
* CVE-2014-3532, CVE-2014-3533: add patches to avoid two separate
......
From 6060aaa0ea1e9bbe1dd7a1864c8df52e333a45ee Mon Sep 17 00:00:00 2001
From: Alban Crequy <alban.crequy@collabora.co.uk>
Date: Thu, 10 Jul 2014 15:08:06 +0100
Subject: [PATCH 01/10] system bus limit: use max_replies_per_connection=128 by
default
This addresses CVE-2014-3638.
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=81053
Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
(cherry picked from commit 5bc7f9519ebc6117ba300c704794b36b87c2194b)
---
bus/config-parser.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/bus/config-parser.c b/bus/config-parser.c
index 07e8fbb..e4a0262 100644
--- a/bus/config-parser.c
+++ b/bus/config-parser.c
@@ -456,7 +456,7 @@ bus_config_parser_new (const DBusString *basedir,
/* this is effectively a limit on message queue size for messages
* that require a reply
*/
- parser->limits.max_replies_per_connection = 1024*8;
+ parser->limits.max_replies_per_connection = 128;
}
parser->refcount = 1;
--
2.1.0
From 346da99f7620e6901e7c7babd4590fcc5aac32bf Mon Sep 17 00:00:00 2001
From: Simon McVittie <simon.mcvittie@collabora.co.uk>
Date: Mon, 15 Sep 2014 19:20:03 +0100
Subject: [PATCH 02/10] config: add new limit: pending_fd_timeout
When a file descriptor is passed to dbus-daemon, the associated D-Bus message
might not be fully sent to dbus-daemon yet. Dbus-daemon keeps the file
descriptor in the DBusMessageLoader of the connection, waiting for the rest of
the message. If the client stops sending the remaining bytes, dbus-daemon will
wait forever and keep that file descriptor.
This patch adds pending_fd_timeout (milliseconds) in the configuration to
disconnect a connection after a timeout when a file descriptor was sent but not
the remaining message.
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=80559
Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
Conflicts:
cmake/bus/dbus-daemon.xml
---
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
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
From a3477feb7aa8658602cceb8d29ae370a83002172 Mon Sep 17 00:00:00 2001
From: Alban Crequy <alban.crequy@collabora.co.uk>
Date: Tue, 8 Jul 2014 12:00:58 +0100
Subject: [PATCH 03/10] config: change default auth_timeout to 5 seconds
This partially addresses CVE-2014-3639.
This will change the default on the system bus where the limit
<limit name="auth_timeout">...</limit>
is not specified.
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=80919
Reviewed-by: Thiago Macieira <thiago@kde.org>
Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
(cherry picked from commit 54d26df52b6a394bea175651d1d7ad2ab3f87dea)
---
bus/config-parser.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/bus/config-parser.c b/bus/config-parser.c
index cc29ef4..95d69a4 100644
--- a/bus/config-parser.c
+++ b/bus/config-parser.c
@@ -427,7 +427,7 @@ bus_config_parser_new (const DBusString *basedir,
* and legitimate auth will fail. If interactive auth (ask user for
* password) is allowed, then potentially it has to be quite long.
*/
- parser->limits.auth_timeout = 30000; /* 30 seconds */
+ parser->limits.auth_timeout = 5000; /* 5 seconds */
parser->limits.max_incomplete_connections = 64;
parser->limits.max_connections_per_user = 256;
--
2.1.0
From e17a921be676bcc89373ec1a9f368fe8b36f1073 Mon Sep 17 00:00:00 2001
From: Alban Crequy <alban.crequy@collabora.co.uk>
Date: Mon, 21 Jul 2014 17:34:08 +0100
Subject: [PATCH 05/10] config: add new limit: pending_fd_timeout
This is one of four commits needed to address CVE-2014-3637.
When a file descriptor is passed to dbus-daemon, the associated D-Bus message
might not be fully sent to dbus-daemon yet. Dbus-daemon keeps the file
descriptor in the DBusMessageLoader of the connection, waiting for the rest of
the message. If the client stops sending the remaining bytes, dbus-daemon will
wait forever and keep that file descriptor.
This patch adds pending_fd_timeout (milliseconds) in the configuration to
disconnect a connection after a timeout when a file descriptor was sent but not
the remaining message.
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=80559
Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
(cherry picked from commit bbf11cd5f92064c7c8af61ad4d9ff41f3a039abc)
Conflicts:
cmake/bus/dbus-daemon.xml
---
bus/bus.c | 6 ++++++
bus/bus.h | 2 ++
bus/config-parser.c | 12 ++++++++++++
bus/session.conf.in | 1 +
cmake/bus/dbus-daemon.xml | 6 +++++-
5 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/bus/bus.c b/bus/bus.c
index 7ffe772..c4eadc2 100644
--- a/bus/bus.c
+++ b/bus/bus.c
@@ -1229,6 +1229,12 @@ bus_context_get_auth_timeout (BusContext *context)
}
int
+bus_context_get_pending_fd_timeout (BusContext *context)
+{
+ return context->limits.pending_fd_timeout;
+}
+
+int
bus_context_get_max_completed_connections (BusContext *context)
{
return context->limits.max_completed_connections;
diff --git a/bus/bus.h b/bus/bus.h
index 400c9d0..7d0b369 100644
--- a/bus/bus.h
+++ b/bus/bus.h
@@ -54,6 +54,7 @@ typedef struct
long max_message_unix_fds; /**< Max number of unix fds of a single message*/
int activation_timeout; /**< How long to wait for an activation to time out */
int auth_timeout; /**< How long to wait for an authentication to time out */
+ int pending_fd_timeout; /**< How long to wait for a D-Bus message with a fd to time out */
int max_completed_connections; /**< Max number of authorized connections */
int max_incomplete_connections; /**< Max number of incomplete connections */
int max_connections_per_user; /**< Max number of connections auth'd as same user */
@@ -106,6 +107,7 @@ BusClientPolicy* bus_context_create_client_policy (BusContext
DBusError *error);
int bus_context_get_activation_timeout (BusContext *context);
int bus_context_get_auth_timeout (BusContext *context);
+int bus_context_get_pending_fd_timeout (BusContext *context);
int bus_context_get_max_completed_connections (BusContext *context);
int bus_context_get_max_incomplete_connections (BusContext *context);
int bus_context_get_max_connections_per_user (BusContext *context);
diff --git a/bus/config-parser.c b/bus/config-parser.c
index 95d69a4..897667e 100644
--- a/bus/config-parser.c
+++ b/bus/config-parser.c
@@ -428,6 +428,11 @@ bus_config_parser_new (const DBusString *basedir,
* password) is allowed, then potentially it has to be quite long.
*/
parser->limits.auth_timeout = 5000; /* 5 seconds */
+
+ /* Do not allow a fd to stay forever in dbus-daemon
+ * https://bugs.freedesktop.org/show_bug.cgi?id=80559
+ */
+ parser->limits.pending_fd_timeout = 150000; /* 2.5 minutes */
parser->limits.max_incomplete_connections = 64;
parser->limits.max_connections_per_user = 256;
@@ -1891,6 +1896,12 @@ set_limit (BusConfigParser *parser,
must_be_int = TRUE;
parser->limits.auth_timeout = value;
}
+ else if (strcmp (name, "pending_fd_timeout") == 0)
+ {
+ must_be_positive = TRUE;
+ must_be_int = TRUE;
+ parser->limits.pending_fd_timeout = value;
+ }
else if (strcmp (name, "reply_timeout") == 0)
{
must_be_positive = TRUE;
@@ -3097,6 +3108,7 @@ limits_equal (const BusLimits *a,
|| a->max_message_unix_fds == b->max_message_unix_fds
|| a->activation_timeout == b->activation_timeout
|| a->auth_timeout == b->auth_timeout
+ || a->pending_fd_timeout == b->pending_fd_timeout
|| a->max_completed_connections == b->max_completed_connections
|| a->max_incomplete_connections == b->max_incomplete_connections
|| a->max_connections_per_user == b->max_connections_per_user
diff --git a/bus/session.conf.in b/bus/session.conf.in
index 6ce8503..2ee1c31 100644
--- a/bus/session.conf.in
+++ b/bus/session.conf.in
@@ -53,6 +53,7 @@
limit is also relatively low -->
<limit name="service_start_timeout">120000</limit>
<limit name="auth_timeout">240000</limit>
+ <limit name="pending_fd_timeout">150000</limit>
<limit name="max_completed_connections">100000</limit>
<limit name="max_incomplete_connections">10000</limit>
<limit name="max_connections_per_user">100000</limit>
diff --git a/cmake/bus/dbus-daemon.xml b/cmake/bus/dbus-daemon.xml
index f331699..fb517e2 100644
--- a/cmake/bus/dbus-daemon.xml
+++ b/cmake/bus/dbus-daemon.xml
@@ -401,7 +401,11 @@ Available limit names are:</para>
"auth_timeout" : milliseconds (thousandths) a
connection is given to
authenticate
- "max_completed_connections" : max number of authenticated connections
+ "pending_fd_timeout" : milliseconds (thousandths) a
+ fd is given to be transmitted to
+ dbus-daemon before disconnecting the
+ connection
+ "max_completed_connections" : max number of authenticated connections
"max_incomplete_connections" : max number of unauthenticated
connections
"max_connections_per_user" : max number of completed connections from
--
2.1.0
From 52abb5172f7426bb3f1dbe63a2b3a2d2ea7e7ac2 Mon Sep 17 00:00:00 2001
From: Alban Crequy <alban.crequy@collabora.co.uk>
Date: Fri, 18 Jul 2014 16:45:07 +0100
Subject: [PATCH 06/10] DBusConnection: implements
_dbus_connection_get_pending_fds_count
This is one of four commits needed to address CVE-2014-3637.
This will allow the bus to know whether there are pending file descriptors in a
DBusConnection's DBusMessageLoader.
https://bugs.freedesktop.org/show_bug.cgi?id=80559
Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
[fix compilation on platforms that do not HAVE_UNIX_FD_PASSING -smcv]
Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
(cherry picked from commit 995734750cea65012537748ee56488c707d2f027)
Conflicts:
dbus/dbus-message.c
---
dbus/dbus-connection-internal.h | 1 +
dbus/dbus-connection.c | 11 +++++++++++
dbus/dbus-message-internal.h | 1 +
dbus/dbus-message.c | 15 +++++++++++++++
dbus/dbus-transport.c | 11 +++++++++++
dbus/dbus-transport.h | 1 +
6 files changed, 40 insertions(+)
diff --git a/dbus/dbus-connection-internal.h b/dbus/dbus-connection-internal.h
index 3d37f18..f5edf3c 100644
--- a/dbus/dbus-connection-internal.h
+++ b/dbus/dbus-connection-internal.h
@@ -100,6 +100,7 @@ void _dbus_connection_test_get_locks (DBusConnectio
DBusMutex **io_path_mutex_loc,
DBusCondVar **dispatch_cond_loc,
DBusCondVar **io_path_cond_loc);
+int _dbus_connection_get_pending_fds_count (DBusConnection *connection);
/* if DBUS_ENABLE_STATS */
void _dbus_connection_get_stats (DBusConnection *connection,
diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c
index b175a44..07a9ebf 100644
--- a/dbus/dbus-connection.c
+++ b/dbus/dbus-connection.c
@@ -2532,6 +2532,17 @@ _dbus_connection_block_pending_call (DBusPendingCall *pending)
dbus_pending_call_unref (pending);
}
+/**
+ * Return how many file descriptors are pending in the loader
+ *
+ * @param connection the connection
+ */
+int
+_dbus_connection_get_pending_fds_count (DBusConnection *connection)
+{
+ return _dbus_transport_get_pending_fds_count (connection->transport);
+}
+
/** @} */
/**
diff --git a/dbus/dbus-message-internal.h b/dbus/dbus-message-internal.h
index c194873..de03edd 100644
--- a/dbus/dbus-message-internal.h
+++ b/dbus/dbus-message-internal.h
@@ -97,6 +97,7 @@ long _dbus_message_loader_get_max_message_size (DBusMessageLoader
void _dbus_message_loader_set_max_message_unix_fds(DBusMessageLoader *loader,
long n);
long _dbus_message_loader_get_max_message_unix_fds(DBusMessageLoader *loader);
+int _dbus_message_loader_get_pending_fds_count (DBusMessageLoader *loader);
typedef struct DBusInitialFDs DBusInitialFDs;
DBusInitialFDs *_dbus_check_fdleaks_enter (void);
diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c
index b0c641e..5d70f69 100644
--- a/dbus/dbus-message.c
+++ b/dbus/dbus-message.c
@@ -4428,6 +4428,21 @@ static DBusDataSlotAllocator slot_allocator;
_DBUS_DEFINE_GLOBAL_LOCK (message_slots);
/**
+ * Return how many file descriptors are pending in the loader
+ *
+ * @param loader the loader
+ */
+int
+_dbus_message_loader_get_pending_fds_count (DBusMessageLoader *loader)
+{
+#ifdef HAVE_UNIX_FD_PASSING
+ return loader->n_unix_fds;
+#else
+ return 0;
+#endif
+}
+
+/**
* Allocates an integer ID to be used for storing application-specific
* data on any DBusMessage. The allocated ID may then be used
* with dbus_message_set_data() and dbus_message_get_data().
diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c
index 6b58fda..e4d03c1 100644
--- a/dbus/dbus-transport.c
+++ b/dbus/dbus-transport.c
@@ -1491,6 +1491,17 @@ _dbus_transport_set_allow_anonymous (DBusTransport *transport,
transport->allow_anonymous = value != FALSE;
}
+/**
+ * Return how many file descriptors are pending in the loader
+ *
+ * @param transport the transport
+ */
+int
+_dbus_transport_get_pending_fds_count (DBusTransport *transport)
+{
+ return _dbus_message_loader_get_pending_fds_count (transport->loader);
+}
+
#ifdef DBUS_ENABLE_STATS
void
_dbus_transport_get_stats (DBusTransport *transport,
diff --git a/dbus/dbus-transport.h b/dbus/dbus-transport.h
index 4b82151..6a3a8b3 100644
--- a/dbus/dbus-transport.h
+++ b/dbus/dbus-transport.h
@@ -96,6 +96,7 @@ dbus_bool_t _dbus_transport_set_auth_mechanisms (DBusTransport
const char **mechanisms);
void _dbus_transport_set_allow_anonymous (DBusTransport *transport,
dbus_bool_t value);
+int _dbus_transport_get_pending_fds_count (DBusTransport *transport);
/* if DBUS_ENABLE_STATS */
void _dbus_transport_get_stats (DBusTransport *transport,
--
2.1.0
From 01e32d6ddcfdcbd63cf1c8053f6e5d2ffdfbaa91 Mon Sep 17 00:00:00 2001
From: Alban Crequy <alban.crequy@collabora.co.uk>
Date: Fri, 18 Jul 2014 17:28:32 +0100
Subject: [PATCH 07/10] DBusConnection: implements
_dbus_connection_set_pending_fds_function
This is one of four commits needed to address CVE-2014-3637.
This will allow the bus to be notified whenever a file descriptor is added or
removed from a DBusConnection's DBusMessageLoader.
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=80559
Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
(cherry picked from commit 8021fd84267ee1394d96f4a119adb57de3971a62)
Conflicts:
dbus/dbus-message.c
---
dbus/dbus-connection-internal.h | 5 +++++
dbus/dbus-connection.c | 16 ++++++++++++++++
dbus/dbus-message-internal.h | 3 +++
dbus/dbus-message-private.h | 2 ++
dbus/dbus-message.c | 25 +++++++++++++++++++++++++
dbus/dbus-transport.c | 16 ++++++++++++++++
dbus/dbus-transport.h | 3 +++
7 files changed, 70 insertions(+)
diff --git a/dbus/dbus-connection-internal.h b/dbus/dbus-connection-internal.h
index f5edf3c..badeabf 100644
--- a/dbus/dbus-connection-internal.h
+++ b/dbus/dbus-connection-internal.h
@@ -44,6 +44,8 @@ typedef enum
/** default timeout value when waiting for a message reply, 25 seconds */
#define _DBUS_DEFAULT_TIMEOUT_VALUE (25 * 1000)
+typedef void (* DBusPendingFdsChangeFunction) (void *data);
+
void _dbus_connection_lock (DBusConnection *connection);
void _dbus_connection_unlock (DBusConnection *connection);
DBusConnection * _dbus_connection_ref_unlocked (DBusConnection *connection);
@@ -101,6 +103,9 @@ void _dbus_connection_test_get_locks (DBusConnectio
DBusCondVar **dispatch_cond_loc,
DBusCondVar **io_path_cond_loc);
int _dbus_connection_get_pending_fds_count (DBusConnection *connection);
+void _dbus_connection_set_pending_fds_function (DBusConnection *connection,
+ DBusPendingFdsChangeFunction callback,
+ void *data);
/* if DBUS_ENABLE_STATS */
void _dbus_connection_get_stats (DBusConnection *connection,
diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c
index 07a9ebf..e1068e3 100644
--- a/dbus/dbus-connection.c
+++ b/dbus/dbus-connection.c
@@ -2543,6 +2543,22 @@ _dbus_connection_get_pending_fds_count (DBusConnection *connection)
return _dbus_transport_get_pending_fds_count (connection->transport);
}
+/**
+ * Register a function to be called whenever the number of pending file
+ * descriptors in the loader change.
+ *
+ * @param connection the connection
+ * @param callback the callback
+ */
+void
+_dbus_connection_set_pending_fds_function (DBusConnection *connection,
+ DBusPendingFdsChangeFunction callback,
+ void *data)
+{
+ _dbus_transport_set_pending_fds_function (connection->transport,
+ callback, data);
+}
+
/** @} */
/**
diff --git a/dbus/dbus-message-internal.h b/dbus/dbus-message-internal.h
index de03edd..76540f4 100644
--- a/dbus/dbus-message-internal.h
+++ b/dbus/dbus-message-internal.h
@@ -98,6 +98,9 @@ void _dbus_message_loader_set_max_message_unix_fds(DBusMessageLoad
long n);
long _dbus_message_loader_get_max_message_unix_fds(DBusMessageLoader *loader);
int _dbus_message_loader_get_pending_fds_count (DBusMessageLoader *loader);
+void _dbus_message_loader_set_pending_fds_function (DBusMessageLoader *loader,
+ void (* callback) (void *),
+