orion / rpms / dbus

Forked from rpms/dbus a year ago
Clone
3dddcf
From 872b085f12f56da25a2dbd9bd0b2dff31d5aea63 Mon Sep 17 00:00:00 2001
3dddcf
From: Simon McVittie <smcv@collabora.com>
3dddcf
Date: Thu, 16 Apr 2020 14:45:11 +0100
3dddcf
Subject: [PATCH] sysdeps-unix: On MSG_CTRUNC, close the fds we did receive
3dddcf
3dddcf
MSG_CTRUNC indicates that we have received fewer fds that we should
3dddcf
have done because the buffer was too small, but we were treating it
3dddcf
as though it indicated that we received *no* fds. If we received any,
3dddcf
we still have to make sure we close them, otherwise they will be leaked.
3dddcf
3dddcf
On the system bus, if an attacker can induce us to leak fds in this
3dddcf
way, that's a local denial of service via resource exhaustion.
3dddcf
3dddcf
Reported-by: Kevin Backhouse, GitHub Security Lab
3dddcf
Fixes: dbus#294
3dddcf
Fixes: CVE-2020-12049
3dddcf
Fixes: GHSL-2020-057
3dddcf
---
3dddcf
 dbus/dbus-sysdeps-unix.c | 32 ++++++++++++++++++++------------
3dddcf
 1 file changed, 20 insertions(+), 12 deletions(-)
3dddcf
3dddcf
diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c
3dddcf
index b5fc24663..b176dae1a 100644
3dddcf
--- a/dbus/dbus-sysdeps-unix.c
3dddcf
+++ b/dbus/dbus-sysdeps-unix.c
3dddcf
@@ -435,18 +435,6 @@ _dbus_read_socket_with_unix_fds (DBusSocket        fd,
3dddcf
       struct cmsghdr *cm;
3dddcf
       dbus_bool_t found = FALSE;
3dddcf
 
3dddcf
-      if (m.msg_flags & MSG_CTRUNC)
3dddcf
-        {
3dddcf
-          /* Hmm, apparently the control data was truncated. The bad
3dddcf
-             thing is that we might have completely lost a couple of fds
3dddcf
-             without chance to recover them. Hence let's treat this as a
3dddcf
-             serious error. */
3dddcf
-
3dddcf
-          errno = ENOSPC;
3dddcf
-          _dbus_string_set_length (buffer, start);
3dddcf
-          return -1;
3dddcf
-        }
3dddcf
-
3dddcf
       for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm))
3dddcf
         if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS)
3dddcf
           {
3dddcf
@@ -501,6 +489,26 @@ _dbus_read_socket_with_unix_fds (DBusSocket        fd,
3dddcf
       if (!found)
3dddcf
         *n_fds = 0;
3dddcf
 
3dddcf
+      if (m.msg_flags & MSG_CTRUNC)
3dddcf
+        {
3dddcf
+          unsigned int i;
3dddcf
+
3dddcf
+          /* Hmm, apparently the control data was truncated. The bad
3dddcf
+             thing is that we might have completely lost a couple of fds
3dddcf
+             without chance to recover them. Hence let's treat this as a
3dddcf
+             serious error. */
3dddcf
+
3dddcf
+          /* We still need to close whatever fds we *did* receive,
3dddcf
+           * otherwise they'll never get closed. (CVE-2020-12049) */
3dddcf
+          for (i = 0; i < *n_fds; i++)
3dddcf
+            close (fds[i]);
3dddcf
+
3dddcf
+          *n_fds = 0;
3dddcf
+          errno = ENOSPC;
3dddcf
+          _dbus_string_set_length (buffer, start);
3dddcf
+          return -1;
3dddcf
+        }
3dddcf
+
3dddcf
       /* put length back (doesn't actually realloc) */
3dddcf
       _dbus_string_set_length (buffer, start + bytes_read);
3dddcf
 
3dddcf
-- 
3dddcf
GitLab
3dddcf