eb774e
From 51a5bbf9074855b0f4a353ed309938b196c13525 Mon Sep 17 00:00:00 2001
eb774e
From: Simon McVittie <smcv@collabora.com>
eb774e
Date: Fri, 30 Sep 2022 13:46:31 +0100
eb774e
Subject: [PATCH] dbus-marshal-byteswap: Byte-swap Unix fd indexes if needed
eb774e
eb774e
When a D-Bus message includes attached file descriptors, the body of the
eb774e
message contains unsigned 32-bit indexes pointing into an out-of-band
eb774e
array of file descriptors. Some D-Bus APIs like GLib's GDBus refer to
eb774e
these indexes as "handles" for the associated fds (not to be confused
eb774e
with a Windows HANDLE, which is a kernel object).
eb774e
eb774e
The assertion message removed by this commit is arguably correct up to
eb774e
a point: fd-passing is only reasonable on a local machine, and no known
eb774e
operating system allows processes of differing endianness even on a
eb774e
multi-endian ARM or PowerPC CPU, so it makes little sense for the sender
eb774e
to specify a byte-order that differs from the byte-order of the recipient.
eb774e
eb774e
However, this doesn't account for the fact that a malicious sender
eb774e
doesn't have to restrict itself to only doing things that make sense.
eb774e
On a system with untrusted local users, a message sender could crash
eb774e
the system dbus-daemon (a denial of service) by sending a message in
eb774e
the opposite endianness that contains handles to file descriptors.
eb774e
eb774e
Before this commit, if assertions are enabled, attempting to byteswap
eb774e
a fd index would cleanly crash the message recipient with an assertion
eb774e
failure. If assertions are disabled, attempting to byteswap a fd index
eb774e
would silently do nothing without advancing the pointer p, causing the
eb774e
message's type and the pointer into its contents to go out of sync, which
eb774e
can result in a subsequent crash (the crash demonstrated by fuzzing was
eb774e
a use-after-free, but other failure modes might be possible).
eb774e
eb774e
In principle we could resolve this by rejecting wrong-endianness messages
eb774e
from a local sender, but it's actually simpler and less code to treat
eb774e
wrong-endianness messages as valid and byteswap them.
eb774e
eb774e
Thanks: Evgeny Vereshchagin
eb774e
Fixes: ba7daa60 "unix-fd: add basic marshalling code for unix fds"
eb774e
Resolves: https://gitlab.freedesktop.org/dbus/dbus/-/issues/417
eb774e
Resolves: CVE-2022-42012
eb774e
Signed-off-by: Simon McVittie <smcv@collabora.com>
eb774e
(cherry picked from commit 236f16e444e88a984cf12b09225e0f8efa6c5b44)
eb774e
(cherry picked from commit 3fb065b0752db1e298e4ada52cf4adc414f5e946)
eb774e
---
eb774e
 dbus/dbus-marshal-byteswap.c | 6 +-----
eb774e
 1 file changed, 1 insertion(+), 5 deletions(-)
eb774e
eb774e
diff --git a/dbus/dbus-marshal-byteswap.c b/dbus/dbus-marshal-byteswap.c
eb774e
index 27695aafb..7104e9c63 100644
eb774e
--- a/dbus/dbus-marshal-byteswap.c
eb774e
+++ b/dbus/dbus-marshal-byteswap.c
eb774e
@@ -61,6 +61,7 @@ byteswap_body_helper (DBusTypeReader       *reader,
eb774e
         case DBUS_TYPE_BOOLEAN:
eb774e
         case DBUS_TYPE_INT32:
eb774e
         case DBUS_TYPE_UINT32:
eb774e
+        case DBUS_TYPE_UNIX_FD:
eb774e
           {
eb774e
             p = _DBUS_ALIGN_ADDRESS (p, 4);
eb774e
             *((dbus_uint32_t*)p) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)p));
eb774e
@@ -188,11 +189,6 @@ byteswap_body_helper (DBusTypeReader       *reader,
eb774e
           }
eb774e
           break;
eb774e
 
eb774e
-        case DBUS_TYPE_UNIX_FD:
eb774e
-          /* fds can only be passed on a local machine, so byte order must always match */
eb774e
-          _dbus_assert_not_reached("attempted to byteswap unix fds which makes no sense");
eb774e
-          break;
eb774e
-
eb774e
         default:
eb774e
           _dbus_assert_not_reached ("invalid typecode in supposedly-validated signature");
eb774e
           break;
eb774e
-- 
eb774e
GitLab
eb774e