From 07f4c12efe3b9bd45d109bc5fbaf6d9dbf69d78e Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Wed, 11 Jun 2014 12:24:20 +0100 Subject: [PATCH 1/4] If loader contains two messages with fds, don't corrupt the second There were two bugs here: we would previously overwrite the unused fds with the already-used fds instead of the other way round, and we would copy n bytes where we should have copied n ints. Additionally, sending crafted messages in a chosen sequence to a victim system service could cause an invalid file descriptor to be present when dbus-daemon tries to forward one of those crafted messages to the victim, causing sendmsg() to fail with EBADF, which resulted in disconnecting the victim service, which would likely respond to that by exiting. This is a denial of service (fd.o #80469, CVE-2014-3533). Bug: https://bugs.freedesktop.org/show_bug.cgi?id=79694 Bug: https://bugs.freedesktop.org/show_bug.cgi?id=80469 Reviewed-by: Alban Crequy --- dbus/dbus-message.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index c6953d02..78df7558 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -4204,7 +4204,7 @@ load_message (DBusMessageLoader *loader, message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds; loader->n_unix_fds -= n_unix_fds; - memmove(loader->unix_fds + n_unix_fds, loader->unix_fds, loader->n_unix_fds); + memmove (loader->unix_fds, loader->unix_fds + n_unix_fds, loader->n_unix_fds * sizeof (loader->unix_fds[0])); } else message->unix_fds = NULL; From 9ca90648fc870c24d852ce6d7ce9387a9fc9a94a Mon Sep 17 00:00:00 2001 From: Alban Crequy Date: Tue, 24 Jun 2014 17:57:14 +0100 Subject: [PATCH 2/4] Handle ETOOMANYREFS when sending recursive fds (SCM_RIGHTS) Since Linux commit 25888e (from 2.6.37-rc4, Nov 2010), sendmsg() on Unix sockets returns -1 errno=ETOOMANYREFS ("Too many references: cannot splice") when the passfd mechanism (SCM_RIGHTS) is "abusively" used recursively by applications. A malicious client could use this to force a victim system service to be disconnected from the system bus; the victim would likely respond by exiting. This is a denial of service (fd.o #80163, CVE-2014-3532). This patch silently drops the D-Bus message on ETOOMANYREFS and does not close the connection. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=80163 Reviewed-by: Thiago Macieira [altered commit message to explain DoS significance -smcv] Reviewed-by: Simon McVittie --- dbus/dbus-sysdeps.c | 14 ++++++++++++++ dbus/dbus-sysdeps.h | 1 + dbus/dbus-transport-socket.c | 34 +++++++++++++++++++++++++++++++++- 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c index de3a18cb..f4ba0fac 100644 --- a/dbus/dbus-sysdeps.c +++ b/dbus/dbus-sysdeps.c @@ -761,6 +761,20 @@ _dbus_get_is_errno_epipe (void) return errno == EPIPE; } +/** + * See if errno is ETOOMANYREFS + * @returns #TRUE if errno == ETOOMANYREFS + */ +dbus_bool_t +_dbus_get_is_errno_etoomanyrefs (void) +{ +#ifdef ETOOMANYREFS + return errno == ETOOMANYREFS; +#else + return FALSE; +#endif +} + /** * Get error message from errno * @returns _dbus_strerror(errno) diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h index e586946f..21033ebf 100644 --- a/dbus/dbus-sysdeps.h +++ b/dbus/dbus-sysdeps.h @@ -384,6 +384,7 @@ dbus_bool_t _dbus_get_is_errno_eagain_or_ewouldblock (void); dbus_bool_t _dbus_get_is_errno_enomem (void); dbus_bool_t _dbus_get_is_errno_eintr (void); dbus_bool_t _dbus_get_is_errno_epipe (void); +dbus_bool_t _dbus_get_is_errno_etoomanyrefs (void); const char* _dbus_strerror_from_errno (void); void _dbus_disable_sigpipe (void); diff --git a/dbus/dbus-transport-socket.c b/dbus/dbus-transport-socket.c index 774f4598..199d3b54 100644 --- a/dbus/dbus-transport-socket.c +++ b/dbus/dbus-transport-socket.c @@ -645,12 +645,44 @@ do_writing (DBusTransport *transport) { /* EINTR already handled for us */ - /* For some discussion of why we also ignore EPIPE here, see + /* If the other end closed the socket with close() or shutdown(), we + * receive EPIPE here but we must not close the socket yet: there + * might still be some data to read. See: * http://lists.freedesktop.org/archives/dbus/2008-March/009526.html */ if (_dbus_get_is_errno_eagain_or_ewouldblock () || _dbus_get_is_errno_epipe ()) goto out; + + /* Since Linux commit 25888e (from 2.6.37-rc4, Nov 2010), sendmsg() + * on Unix sockets returns -1 errno=ETOOMANYREFS when the passfd + * mechanism (SCM_RIGHTS) is used recursively with a recursion level + * of maximum 4. The kernel does not have an API to check whether + * the passed fds can be forwarded and it can change asynchronously. + * See: + * https://bugs.freedesktop.org/show_bug.cgi?id=80163 + */ + + else if (_dbus_get_is_errno_etoomanyrefs ()) + { + /* We only send fds in the first byte of the message. + * ETOOMANYREFS cannot happen after. + */ + _dbus_assert (socket_transport->message_bytes_written == 0); + + _dbus_verbose (" discard message of %d bytes due to ETOOMANYREFS\n", + total_bytes_to_write); + + socket_transport->message_bytes_written = 0; + _dbus_string_set_length (&socket_transport->encoded_outgoing, 0); + _dbus_string_compact (&socket_transport->encoded_outgoing, 2048); + + /* The message was not actually sent but it needs to be removed + * from the outgoing queue + */ + _dbus_connection_message_sent_unlocked (transport->connection, + message); + } else { _dbus_verbose ("Error writing to remote app: %s\n", From 194f6f758983aacad4ea32dc0038ef19d23c6e21 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 30 Jun 2014 14:18:03 +0100 Subject: [PATCH 3/4] Prepare 1.8.6 in advance --- NEWS | 19 +++++++++++++++++-- configure.ac | 4 ++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 48d3e9b0..0944bf42 100644 --- a/NEWS +++ b/NEWS @@ -1,7 +1,22 @@ -D-Bus 1.8.6 (UNRELEASED) +D-Bus 1.8.6 (2014-06-02) == -Fixes: +Security fixes: + +• On Linux ≥ 2.6.37-rc4, if sendmsg() fails with ETOOMANYREFS, silently drop + the message. This prevents an attack in which a malicious client can + make dbus-daemon disconnect a system service, which is a local + denial of service. + (fd.o #80163, CVE-2014-3532; Alban Crequy) + +• Track remaining Unix file descriptors correctly when more than one + message in quick succession contains fds. This prevents another attack + in which a malicious client can make dbus-daemon disconnect a system + service. + (fd.o #79694, fd.o #80469, CVE-2014-3533; Alejandro Martínez Suárez, + Simon McVittie, Alban Crequy) + +Other fixes: • When dbus-launch --exit-with-session starts a dbus-daemon but then cannot attach to a session, kill the dbus-daemon as intended diff --git a/configure.ac b/configure.ac index 13d0aa94..8ffbb5c3 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.63]) m4_define([dbus_major_version], [1]) m4_define([dbus_minor_version], [8]) -m4_define([dbus_micro_version], [5]) +m4_define([dbus_micro_version], [6]) m4_define([dbus_version], [dbus_major_version.dbus_minor_version.dbus_micro_version]) AC_INIT([dbus],[dbus_version],[https://bugs.freedesktop.org/enter_bug.cgi?product=dbus],[dbus]) @@ -37,7 +37,7 @@ LT_CURRENT=11 ## increment any time the source changes; set to ## 0 if you increment CURRENT -LT_REVISION=5 +LT_REVISION=6 ## increment if any interfaces have been added; set to 0 ## if any interfaces have been changed or removed. removal has From 8f31484171dbffea56600daf6b6be407bd79d759 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Wed, 2 Jul 2014 18:24:44 +0100 Subject: [PATCH 4/4] start 1.8.7 --- NEWS | 5 +++++ configure.ac | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 0944bf42..3d5373fc 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,8 @@ +D-Bus 1.8.8 (UNRELEASED) +== + +... + D-Bus 1.8.6 (2014-06-02) == diff --git a/configure.ac b/configure.ac index 8ffbb5c3..5412db2e 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.63]) m4_define([dbus_major_version], [1]) m4_define([dbus_minor_version], [8]) -m4_define([dbus_micro_version], [6]) +m4_define([dbus_micro_version], [7]) m4_define([dbus_version], [dbus_major_version.dbus_minor_version.dbus_micro_version]) AC_INIT([dbus],[dbus_version],[https://bugs.freedesktop.org/enter_bug.cgi?product=dbus],[dbus])