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