[dbus/f20] Backport patches from dbus-1.6
Colin Walters
walters at fedoraproject.org
Wed Jul 2 22:31:31 UTC 2014
commit 2fbfaed9f8e2b1fc6f3534867bf79459a03abdc2
Author: Colin Walters <walters at verbum.org>
Date: Wed Jul 2 18:31:14 2014 -0400
Backport patches from dbus-1.6
- Fixes CVE-2014-3477 (fd.o#78979)
- Fixes CVE-2014-3532 (fd.o#80163)
- Fixes CVE-2014-3533 (fd.o#80469)
- Resolves #1115636
...77-deliver-activation-errors-correctly-fi.patch | 150 ++++++++++++++++++++
...MANYREFS-when-sending-recursive-fds-SCM_R.patch | 116 +++++++++++++++
...ontains-two-messages-with-fds-don-t-corru.patch | 40 +++++
dbus.spec | 15 ++-
4 files changed, 320 insertions(+), 1 deletions(-)
---
diff --git a/0001-CVE-2014-3477-deliver-activation-errors-correctly-fi.patch b/0001-CVE-2014-3477-deliver-activation-errors-correctly-fi.patch
new file mode 100644
index 0000000..374ace1
--- /dev/null
+++ b/0001-CVE-2014-3477-deliver-activation-errors-correctly-fi.patch
@@ -0,0 +1,150 @@
+From cab1c56bb9d70469128d2ae1c40539c0d3b30f13 Mon Sep 17 00:00:00 2001
+From: Alban Crequy <alban.crequy at collabora.co.uk>
+Date: Tue, 20 May 2014 14:37:37 +0100
+Subject: [PATCH] CVE-2014-3477: deliver activation errors correctly, fixing
+ Denial of Service
+
+How it should work:
+
+When a D-Bus message activates a service, LSMs (SELinux or AppArmor) check
+whether the message can be delivered after the service has been activated. The
+service is considered activated when its well-known name is requested with
+org.freedesktop.DBus.RequestName. When the message delivery is denied, the
+service stays activated but should not receive the activating message (the
+message which triggered the activation). dbus-daemon is supposed to drop the
+activating message and reply to the sender with a D-Bus error message.
+
+However, it does not work as expected:
+
+1. The error message is delivered to the service instead of being delivered to
+ the sender. As an example, the error message could be something like:
+
+ An SELinux policy prevents this sender from sending this
+ message to this recipient, [...] member="MaliciousMethod"
+
+ If the sender and the service are malicious confederates and agree on a
+ protocol to insert information in the member name, the sender can leak
+ information to the service, even though the LSM attempted to block the
+ communication between the sender and the service.
+
+2. The error message is delivered as a reply to the RequestName call from
+ service. It means the activated service will believe it cannot request the
+ name and might exit. The sender could activate the service frequently and
+ systemd will give up activating it. Thus the denial of service.
+
+The following changes fix the bug:
+- bus_activation_send_pending_auto_activation_messages() only returns an error
+ in case of OOM. The prototype is changed to return TRUE, or FALSE on OOM
+ (and its only caller sets the OOM error).
+- When a client is not allowed to talk to the service, a D-Bus error message
+ is pre-allocated to be delivered to the client as part of the transaction.
+ The error is not propagated to the caller so RequestName will not fail
+ (except on OOM).
+
+[fixed a misleading comment -smcv]
+
+Bug: https://bugs.freedesktop.org/show_bug.cgi?id=78979
+Reviewed-by: Simon McVittie <simon.mcvittie at collabora.co.uk>
+Reviewed-by: Colin Walters <walters at verbum.org>
+---
+ bus/activation.c | 27 ++++++++++++++++++++-------
+ bus/activation.h | 3 +--
+ bus/services.c | 5 +++--
+ 3 files changed, 24 insertions(+), 11 deletions(-)
+
+diff --git a/bus/activation.c b/bus/activation.c
+index ea48a26..280cc01 100644
+--- a/bus/activation.c
++++ b/bus/activation.c
+@@ -1162,14 +1162,11 @@ bus_activation_service_created (BusActivation *activation,
+ dbus_bool_t
+ bus_activation_send_pending_auto_activation_messages (BusActivation *activation,
+ BusService *service,
+- BusTransaction *transaction,
+- DBusError *error)
++ BusTransaction *transaction)
+ {
+ BusPendingActivation *pending_activation;
+ DBusList *link;
+
+- _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+-
+ /* Check if it's a pending activation */
+ pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations,
+ bus_service_get_name (service));
+@@ -1186,6 +1183,9 @@ bus_activation_send_pending_auto_activation_messages (BusActivation *activation
+ if (entry->auto_activation && (entry->connection == NULL || dbus_connection_get_is_connected (entry->connection)))
+ {
+ DBusConnection *addressed_recipient;
++ DBusError error;
++
++ dbus_error_init (&error);
+
+ addressed_recipient = bus_service_get_primary_owners_connection (service);
+
+@@ -1193,8 +1193,22 @@ bus_activation_send_pending_auto_activation_messages (BusActivation *activation
+ if (!bus_dispatch_matches (transaction,
+ entry->connection,
+ addressed_recipient,
+- entry->activation_message, error))
+- goto error;
++ entry->activation_message, &error))
++ {
++ /* If permission is denied, we just want to return the error
++ * to the original method invoker; in particular, we don't
++ * want to make the RequestName call fail with that error
++ * (see fd.o #78979, CVE-2014-3477). */
++ if (!bus_transaction_send_error_reply (transaction, entry->connection,
++ &error, entry->activation_message))
++ {
++ bus_connection_send_oom_error (entry->connection,
++ entry->activation_message);
++ }
++
++ link = next;
++ continue;
++ }
+ }
+
+ link = next;
+@@ -1203,7 +1217,6 @@ bus_activation_send_pending_auto_activation_messages (BusActivation *activation
+ if (!add_restore_pending_to_transaction (transaction, pending_activation))
+ {
+ _dbus_verbose ("Could not add cancel hook to transaction to revert removing pending activation\n");
+- BUS_SET_OOM (error);
+ goto error;
+ }
+
+diff --git a/bus/activation.h b/bus/activation.h
+index 97f25b1..fc5d426 100644
+--- a/bus/activation.h
++++ b/bus/activation.h
+@@ -62,8 +62,7 @@ dbus_bool_t dbus_activation_systemd_failure (BusActivation *activation,
+
+ dbus_bool_t bus_activation_send_pending_auto_activation_messages (BusActivation *activation,
+ BusService *service,
+- BusTransaction *transaction,
+- DBusError *error);
++ BusTransaction *transaction);
+
+
+ #endif /* BUS_ACTIVATION_H */
+diff --git a/bus/services.c b/bus/services.c
+index 01a720e..584485b 100644
+--- a/bus/services.c
++++ b/bus/services.c
+@@ -588,8 +588,9 @@ bus_registry_acquire_service (BusRegistry *registry,
+ activation = bus_context_get_activation (registry->context);
+ retval = bus_activation_send_pending_auto_activation_messages (activation,
+ service,
+- transaction,
+- error);
++ transaction);
++ if (!retval)
++ BUS_SET_OOM (error);
+
+ out:
+ return retval;
+--
+1.8.3.1
+
diff --git a/0001-Handle-ETOOMANYREFS-when-sending-recursive-fds-SCM_R.patch b/0001-Handle-ETOOMANYREFS-when-sending-recursive-fds-SCM_R.patch
new file mode 100644
index 0000000..8d05a7b
--- /dev/null
+++ b/0001-Handle-ETOOMANYREFS-when-sending-recursive-fds-SCM_R.patch
@@ -0,0 +1,116 @@
+From 8c7176019fbc2e8fee41d93ce82ac2603fe57d67 Mon Sep 17 00:00:00 2001
+From: Alban Crequy <alban.crequy at collabora.co.uk>
+Date: Tue, 24 Jun 2014 17:57:14 +0100
+Subject: [PATCH] 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 <thiago at kde.org>
+[altered commit message to explain DoS significance -smcv]
+Reviewed-by: Simon McVittie <simon.mcvittie at collabora.co.uk>
+---
+ 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 04fb8d7..8ed7da9 100644
+--- a/dbus/dbus-sysdeps.c
++++ b/dbus/dbus-sysdeps.c
+@@ -760,6 +760,20 @@ _dbus_get_is_errno_epipe (void)
+ }
+
+ /**
++ * 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 eee9160..df4c5e0 100644
+--- a/dbus/dbus-sysdeps.h
++++ b/dbus/dbus-sysdeps.h
+@@ -373,6 +373,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 544d00a..26d2b73 100644
+--- a/dbus/dbus-transport-socket.c
++++ b/dbus/dbus-transport-socket.c
+@@ -646,12 +646,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",
+--
+1.8.3.1
+
diff --git a/0001-If-loader-contains-two-messages-with-fds-don-t-corru.patch b/0001-If-loader-contains-two-messages-with-fds-don-t-corru.patch
new file mode 100644
index 0000000..e272bce
--- /dev/null
+++ b/0001-If-loader-contains-two-messages-with-fds-don-t-corru.patch
@@ -0,0 +1,40 @@
+From b9c338e32390f953d4c9772daef31187a117b376 Mon Sep 17 00:00:00 2001
+From: Simon McVittie <simon.mcvittie at collabora.co.uk>
+Date: Wed, 11 Jun 2014 12:24:20 +0100
+Subject: [PATCH] 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 <alban.crequy at collabora.co.uk>
+---
+ 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 a34ea1d..fc61ae7 100644
+--- a/dbus/dbus-message.c
++++ b/dbus/dbus-message.c
+@@ -4129,7 +4129,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;
+--
+1.8.3.1
+
diff --git a/dbus.spec b/dbus.spec
index 8f0785f..4d0914a 100644
--- a/dbus.spec
+++ b/dbus.spec
@@ -17,7 +17,7 @@ Summary: D-BUS message bus
Name: dbus
Epoch: 1
Version: 1.6.12
-Release: 8%{?dist}
+Release: 9%{?dist}
URL: http://www.freedesktop.org/software/dbus/
#VCS: git:git://git.freedesktop.org/git/dbus/dbus
Source0: http://dbus.freedesktop.org/releases/dbus/%{name}-%{version}.tar.gz
@@ -61,6 +61,9 @@ Patch1: 0001-name-test-Don-t-run-test-autolaunch-if-we-don-t-have.patch
Patch2: 0001-test-marshal-Ensure-we-use-suitably-aligned-buffers.patch
Patch3: avoid-undefined-7c00ed22d9b5c33f5b33221e906946b11a9bde3b.patch
Patch4: 0001-_dbus_babysitter_unref-avoid-infinite-loop-if-waitpi.patch
+Patch5: 0001-CVE-2014-3477-deliver-activation-errors-correctly-fi.patch
+Patch6: 0001-If-loader-contains-two-messages-with-fds-don-t-corru.patch
+Patch7: 0001-Handle-ETOOMANYREFS-when-sending-recursive-fds-SCM_R.patch
%description
D-BUS is a system for sending messages between applications. It is
@@ -114,6 +117,9 @@ in this separate package so server systems need not install X.
%patch2 -p1
%patch3 -p1
%patch4 -p1
+%patch5 -p1
+%patch6 -p1
+%patch7 -p1
%build
if test -f autogen.sh; then env NOCONFIGURE=1 ./autogen.sh; else autoreconf -v -f -i; fi
@@ -262,6 +268,13 @@ fi
%{_includedir}/*
%changelog
+* Wed Jul 2 2014 Colin Walters <walters at redhat.com> - 1:1.6.12-9
+- Backport patches from dbus-1.6
+- Fixes CVE-2014-3477 (fd.o#78979)
+- Fixes CVE-2014-3532 (fd.o#80163)
+- Fixes CVE-2014-3533 (fd.o#80469)
+- Resolves #1115636
+
* Thu Dec 26 2013 Dan HorĂ¡k <dan[at]danny.cz> - 1:1.6.12-8
- valgrind is available only on selected arches
More information about the scm-commits
mailing list