amigadave / rpms / dbus

Forked from rpms/dbus 5 years ago
Clone
Colin Walters 95a06ee
From 450d975046bbd54271da62ce5fcbe50113f2e453 Mon Sep 17 00:00:00 2001
Colin Walters 95a06ee
From: Colin Walters <walters@verbum.org>
Colin Walters 95a06ee
Date: Wed, 22 Aug 2012 10:03:34 -0400
Colin Walters 95a06ee
Subject: [PATCH] CVE-2012-3524: Don't access environment variables or run
Colin Walters 95a06ee
 dbus-launch when setuid
Colin Walters 95a06ee
Colin Walters 95a06ee
This matches a corresponding change in GLib.  See
Colin Walters 95a06ee
glib/gutils.c:g_check_setuid().
Colin Walters 95a06ee
Colin Walters 95a06ee
Some programs attempt to use libdbus when setuid; notably the X.org
Colin Walters 95a06ee
server is shipped in such a configuration. libdbus never had an
Colin Walters 95a06ee
explicit policy about its use in setuid programs.
Colin Walters 95a06ee
Colin Walters 95a06ee
I'm not sure whether we should advertise such support.  However, given
Colin Walters 95a06ee
that there are real-world programs that do this currently, we can make
Colin Walters 95a06ee
them safer with not too much effort.
Colin Walters 95a06ee
Colin Walters 95a06ee
Better to fix a problem caused by an interaction between two
Colin Walters 95a06ee
components in *both* places if possible.
Colin Walters 95a06ee
Colin Walters 95a06ee
How to determine whether or not we're running in a privilege-escalated
Colin Walters 95a06ee
path is operating system specific.  Note that GTK+'s code to check
Colin Walters 95a06ee
euid versus uid worked historically on Unix, more modern systems have
Colin Walters 95a06ee
filesystem capabilities and SELinux domain transitions, neither of
Colin Walters 95a06ee
which are captured by the uid comparison.
Colin Walters 95a06ee
Colin Walters 95a06ee
On Linux/glibc, the way this works is that the kernel sets an
Colin Walters 95a06ee
AT_SECURE flag in the ELF auxiliary vector, and glibc looks for it on
Colin Walters 95a06ee
startup.  If found, then glibc sets a public-but-undocumented
Colin Walters 95a06ee
__libc_enable_secure variable which we can use.  Unfortunately, while
Colin Walters 95a06ee
it *previously* worked to check this variable, a combination of newer
Colin Walters 95a06ee
binutils and RPM break it:
Colin Walters 95a06ee
http://www.openwall.com/lists/owl-dev/2012/08/14/1
Colin Walters 95a06ee
Colin Walters 95a06ee
So for now on Linux/glibc, we fall back to the historical Unix version
Colin Walters 95a06ee
until we get glibc fixed.
Colin Walters 95a06ee
Colin Walters 95a06ee
On some BSD variants, there is a issetugid() function.  On other Unix
Colin Walters 95a06ee
variants, we fall back to what GTK+ has been doing.
Colin Walters 95a06ee
Colin Walters 95a06ee
Reported-by: Sebastian Krahmer <krahmer@suse.de>
Colin Walters 95a06ee
Signed-off-by: Colin Walters <walters@verbum.org>
Colin Walters 95a06ee
---
Colin Walters 95a06ee
 configure.ac             |  2 +-
Colin Walters 95a06ee
 dbus/dbus-keyring.c      |  7 +++++
Colin Walters 95a06ee
 dbus/dbus-sysdeps-unix.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++
Colin Walters 95a06ee
 dbus/dbus-sysdeps-win.c  |  6 ++++
Colin Walters 95a06ee
 dbus/dbus-sysdeps.c      |  5 ++++
Colin Walters 95a06ee
 dbus/dbus-sysdeps.h      |  1 +
Colin Walters 95a06ee
 6 files changed, 94 insertions(+), 1 deletion(-)
Colin Walters 95a06ee
Colin Walters 95a06ee
diff --git a/configure.ac b/configure.ac
Colin Walters 95a06ee
index e2c9bdf..b0f2ec2 100644
Colin Walters 95a06ee
--- a/configure.ac
Colin Walters 95a06ee
+++ b/configure.ac
Colin Walters 95a06ee
@@ -595,7 +595,7 @@ AC_DEFINE_UNQUOTED([DBUS_USE_SYNC], [$have_sync], [Use the gcc __sync extension]
Colin Walters 95a06ee
 AC_SEARCH_LIBS(socket,[socket network])
Colin Walters 95a06ee
 AC_CHECK_FUNC(gethostbyname,,[AC_CHECK_LIB(nsl,gethostbyname)])
Colin Walters 95a06ee
 
Colin Walters 95a06ee
-AC_CHECK_FUNCS(vsnprintf vasprintf nanosleep usleep setenv clearenv unsetenv socketpair getgrouplist fpathconf setrlimit poll setlocale localeconv strtoll strtoull)
Colin Walters 95a06ee
+AC_CHECK_FUNCS(vsnprintf vasprintf nanosleep usleep setenv clearenv unsetenv socketpair getgrouplist fpathconf setrlimit poll setlocale localeconv strtoll strtoull issetugid getresuid)
Colin Walters 95a06ee
 
Colin Walters 95a06ee
 AC_CHECK_HEADERS([syslog.h])
Colin Walters 95a06ee
 if test "x$ac_cv_header_syslog_h" = "xyes"; then
Colin Walters 95a06ee
diff --git a/dbus/dbus-keyring.c b/dbus/dbus-keyring.c
Colin Walters 95a06ee
index 23b9df5..3b9ce31 100644
Colin Walters 95a06ee
--- a/dbus/dbus-keyring.c
Colin Walters 95a06ee
+++ b/dbus/dbus-keyring.c
Colin Walters 95a06ee
@@ -717,6 +717,13 @@ _dbus_keyring_new_for_credentials (DBusCredentials  *credentials,
Colin Walters 95a06ee
   DBusCredentials *our_credentials;
Colin Walters 95a06ee
   
Colin Walters 95a06ee
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
Colin Walters 95a06ee
+
Colin Walters 95a06ee
+  if (_dbus_check_setuid ())
Colin Walters 95a06ee
+    {
Colin Walters 95a06ee
+      dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
Colin Walters 95a06ee
+                            "Unable to create DBus keyring when setuid");
Colin Walters 95a06ee
+      return NULL;
Colin Walters 95a06ee
+    }
Colin Walters 95a06ee
   
Colin Walters 95a06ee
   keyring = NULL;
Colin Walters 95a06ee
   error_set = FALSE;
Colin Walters 95a06ee
diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c
Colin Walters 95a06ee
index cef8bd3..b4ecc96 100644
Colin Walters 95a06ee
--- a/dbus/dbus-sysdeps-unix.c
Colin Walters 95a06ee
+++ b/dbus/dbus-sysdeps-unix.c
Colin Walters 95a06ee
@@ -3434,6 +3434,13 @@ _dbus_get_autolaunch_address (const char *scope,
Colin Walters 95a06ee
   DBusString uuid;
Colin Walters 95a06ee
   dbus_bool_t retval;
Colin Walters 95a06ee
 
Colin Walters 95a06ee
+  if (_dbus_check_setuid ())
Colin Walters 95a06ee
+    {
Colin Walters 95a06ee
+      dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
Colin Walters 95a06ee
+                            "Unable to autolaunch when setuid");
Colin Walters 95a06ee
+      return FALSE;
Colin Walters 95a06ee
+    }
Colin Walters 95a06ee
+
Colin Walters 95a06ee
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
Colin Walters 95a06ee
   retval = FALSE;
Colin Walters 95a06ee
 
Colin Walters 95a06ee
@@ -3551,6 +3558,13 @@ _dbus_lookup_launchd_socket (DBusString *socket_path,
Colin Walters 95a06ee
 
Colin Walters 95a06ee
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
Colin Walters 95a06ee
 
Colin Walters 95a06ee
+  if (_dbus_check_setuid ())
Colin Walters 95a06ee
+    {
Colin Walters 95a06ee
+      dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
Colin Walters 95a06ee
+                            "Unable to find launchd socket when setuid");
Colin Walters 95a06ee
+      return FALSE;
Colin Walters 95a06ee
+    }
Colin Walters 95a06ee
+
Colin Walters 95a06ee
   i = 0;
Colin Walters 95a06ee
   argv[i] = "launchctl";
Colin Walters 95a06ee
   ++i;
Colin Walters 95a06ee
@@ -3591,6 +3605,13 @@ _dbus_lookup_session_address_launchd (DBusString *address, DBusError  *error)
Colin Walters 95a06ee
   dbus_bool_t valid_socket;
Colin Walters 95a06ee
   DBusString socket_path;
Colin Walters 95a06ee
 
Colin Walters 95a06ee
+  if (_dbus_check_setuid ())
Colin Walters 95a06ee
+    {
Colin Walters 95a06ee
+      dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED,
Colin Walters 95a06ee
+                            "Unable to find launchd socket when setuid");
Colin Walters 95a06ee
+      return FALSE;
Colin Walters 95a06ee
+    }
Colin Walters 95a06ee
+
Colin Walters 95a06ee
   if (!_dbus_string_init (&socket_path))
Colin Walters 95a06ee
     {
Colin Walters 95a06ee
       _DBUS_SET_OOM (error);
Colin Walters 95a06ee
@@ -4086,4 +4107,57 @@ _dbus_close_all (void)
Colin Walters 95a06ee
     close (i);
Colin Walters 95a06ee
 }
Colin Walters 95a06ee
 
Colin Walters 95a06ee
+/**
Colin Walters 95a06ee
+ * **NOTE**: If you modify this function, please also consider making
Colin Walters 95a06ee
+ * the corresponding change in GLib.  See
Colin Walters 95a06ee
+ * glib/gutils.c:g_check_setuid().
Colin Walters 95a06ee
+ *
Colin Walters 95a06ee
+ * Returns TRUE if the current process was executed as setuid (or an
Colin Walters 95a06ee
+ * equivalent __libc_enable_secure is available).  See:
Colin Walters 95a06ee
+ * http://osdir.com/ml/linux.lfs.hardened/2007-04/msg00032.html
Colin Walters 95a06ee
+ */
Colin Walters 95a06ee
+dbus_bool_t
Colin Walters 95a06ee
+_dbus_check_setuid (void)
Colin Walters 95a06ee
+{
Colin Walters 95a06ee
+  /* TODO: get __libc_enable_secure exported from glibc.
Colin Walters 95a06ee
+   * See http://www.openwall.com/lists/owl-dev/2012/08/14/1
Colin Walters 95a06ee
+   */
Colin Walters 95a06ee
+#if 0 && defined(HAVE_LIBC_ENABLE_SECURE)
Colin Walters 95a06ee
+  {
Colin Walters 95a06ee
+    /* See glibc/include/unistd.h */
Colin Walters 95a06ee
+    extern int __libc_enable_secure;
Colin Walters 95a06ee
+    return __libc_enable_secure;
Colin Walters 95a06ee
+  }
Colin Walters 95a06ee
+#elif defined(HAVE_ISSETUGID)
Colin Walters 95a06ee
+  /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */
Colin Walters 95a06ee
+  return issetugid ();
Colin Walters 95a06ee
+#else
Colin Walters 95a06ee
+  uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
Colin Walters 95a06ee
+  gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
Colin Walters 95a06ee
+
Colin Walters 95a06ee
+  static dbus_bool_t check_setuid_initialised;
Colin Walters 95a06ee
+  static dbus_bool_t is_setuid;
Colin Walters 95a06ee
+
Colin Walters 95a06ee
+  if (_DBUS_UNLIKELY (!check_setuid_initialised))
Colin Walters 95a06ee
+    {
Colin Walters 95a06ee
+#ifdef HAVE_GETRESUID
Colin Walters 95a06ee
+      if (getresuid (&ruid, &euid, &suid) != 0 ||
Colin Walters 95a06ee
+          getresgid (&rgid, &egid, &sgid) != 0)
Colin Walters 95a06ee
+#endif /* HAVE_GETRESUID */
Colin Walters 95a06ee
+        {
Colin Walters 95a06ee
+          suid = ruid = getuid ();
Colin Walters 95a06ee
+          sgid = rgid = getgid ();
Colin Walters 95a06ee
+          euid = geteuid ();
Colin Walters 95a06ee
+          egid = getegid ();
Colin Walters 95a06ee
+        }
Colin Walters 95a06ee
+
Colin Walters 95a06ee
+      check_setuid_initialised = TRUE;
Colin Walters 95a06ee
+      is_setuid = (ruid != euid || ruid != suid ||
Colin Walters 95a06ee
+                   rgid != egid || rgid != sgid);
Colin Walters 95a06ee
+
Colin Walters 95a06ee
+    }
Colin Walters 95a06ee
+  return is_setuid;
Colin Walters 95a06ee
+#endif
Colin Walters 95a06ee
+}
Colin Walters 95a06ee
+
Colin Walters 95a06ee
 /* tests in dbus-sysdeps-util.c */
Colin Walters 95a06ee
diff --git a/dbus/dbus-sysdeps-win.c b/dbus/dbus-sysdeps-win.c
Colin Walters 95a06ee
index 397520a..bc4951b 100644
Colin Walters 95a06ee
--- a/dbus/dbus-sysdeps-win.c
Colin Walters 95a06ee
+++ b/dbus/dbus-sysdeps-win.c
Colin Walters 95a06ee
@@ -3632,6 +3632,12 @@ _dbus_path_is_absolute (const DBusString *filename)
Colin Walters 95a06ee
     return FALSE;
Colin Walters 95a06ee
 }
Colin Walters 95a06ee
 
Colin Walters 95a06ee
+dbus_bool_t
Colin Walters 95a06ee
+_dbus_check_setuid (void)
Colin Walters 95a06ee
+{
Colin Walters 95a06ee
+  return FALSE;
Colin Walters 95a06ee
+}
Colin Walters 95a06ee
+
Colin Walters 95a06ee
 /** @} end of sysdeps-win */
Colin Walters 95a06ee
 /* tests in dbus-sysdeps-util.c */
Colin Walters 95a06ee
 
Colin Walters 95a06ee
diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c
Colin Walters 95a06ee
index 861bfec..04fb8d7 100644
Colin Walters 95a06ee
--- a/dbus/dbus-sysdeps.c
Colin Walters 95a06ee
+++ b/dbus/dbus-sysdeps.c
Colin Walters 95a06ee
@@ -182,6 +182,11 @@ _dbus_setenv (const char *varname,
Colin Walters 95a06ee
 const char*
Colin Walters 95a06ee
 _dbus_getenv (const char *varname)
Colin Walters 95a06ee
 {  
Colin Walters 95a06ee
+  /* Don't respect any environment variables if the current process is
Colin Walters 95a06ee
+   * setuid.  This is the equivalent of glibc's __secure_getenv().
Colin Walters 95a06ee
+   */
Colin Walters 95a06ee
+  if (_dbus_check_setuid ())
Colin Walters 95a06ee
+    return NULL;
Colin Walters 95a06ee
   return getenv (varname);
Colin Walters 95a06ee
 }
Colin Walters 95a06ee
 
Colin Walters 95a06ee
diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h
Colin Walters 95a06ee
index 4052cda..eee9160 100644
Colin Walters 95a06ee
--- a/dbus/dbus-sysdeps.h
Colin Walters 95a06ee
+++ b/dbus/dbus-sysdeps.h
Colin Walters 95a06ee
@@ -87,6 +87,7 @@ typedef struct DBusPipe DBusPipe;
Colin Walters 95a06ee
 
Colin Walters 95a06ee
 void _dbus_abort (void) _DBUS_GNUC_NORETURN;
Colin Walters 95a06ee
 
Colin Walters 95a06ee
+dbus_bool_t _dbus_check_setuid (void);
Colin Walters 95a06ee
 const char* _dbus_getenv (const char *varname);
Colin Walters 95a06ee
 dbus_bool_t _dbus_setenv (const char *varname,
Colin Walters 95a06ee
 			  const char *value);
Colin Walters 95a06ee
-- 
Colin Walters 95a06ee
1.7.11.4
Colin Walters 95a06ee