[glib2/f17] CVE-2012-3524
Colin Walters
walters at fedoraproject.org
Thu Sep 13 22:32:59 UTC 2012
commit 2f0f9a74158048e0f91062ffabaa1f2daf7f3712
Author: Colin Walters <walters at verbum.org>
Date: Thu Sep 13 18:29:16 2012 -0400
CVE-2012-3524
- Resolves: #857226
...24-Hardening-for-being-run-in-a-setuid-en.patch | 255 ++++++++++++++++++++
glib2.spec | 9 +-
2 files changed, 263 insertions(+), 1 deletions(-)
---
diff --git a/0001-CVE-2012-3524-Hardening-for-being-run-in-a-setuid-en.patch b/0001-CVE-2012-3524-Hardening-for-being-run-in-a-setuid-en.patch
new file mode 100644
index 0000000..e4b0496
--- /dev/null
+++ b/0001-CVE-2012-3524-Hardening-for-being-run-in-a-setuid-en.patch
@@ -0,0 +1,255 @@
+From 480b5afb69008faebccef58cd673fc00ebe72857 Mon Sep 17 00:00:00 2001
+From: Colin Walters <walters at verbum.org>
+Date: Wed, 22 Aug 2012 14:26:11 -0400
+Subject: [PATCH] CVE-2012-3524: Hardening for being run in a setuid
+ environment
+
+Some programs attempt to use libglib (or even libgio) when setuid.
+For a long time, GTK+ simply aborted if launched in this
+configuration, but we never had a real policy for GLib.
+
+I'm not sure whether we should advertise such support. However, given
+that there are real-world programs that do this currently, we can make
+them safer with not too much effort.
+
+Better to fix a problem caused by an interaction between two
+components in *both* places if possible.
+
+This patch adds a private function g_check_setuid() which is used to
+first ensure we don't run an external dbus-launch binary if
+DBUS_SESSION_BUS_ADDRESS isn't set.
+
+Second, we also ensure the local VFS is used in this case. The
+gdaemonvfs extension point will end up talking to the session bus
+which is typically undesirable in a setuid context.
+
+Implementing g_check_setuid() is interesting - whether or not we're
+running in a privilege-escalated path is operating system specific.
+Note that GTK+'s code to check euid versus uid worked historically on
+Unix, more modern systems have filesystem capabilities and SELinux
+domain transitions, neither of which are captured by the uid
+comparison.
+
+On Linux/glibc, the way this works is that the kernel sets an
+AT_SECURE flag in the ELF auxiliary vector, and glibc looks for it on
+startup. If found, then glibc sets a public-but-undocumented
+__libc_enable_secure variable which we can use. Unfortunately, while
+it *previously* worked to check this variable, a combination of newer
+binutils and RPM break it:
+http://www.openwall.com/lists/owl-dev/2012/08/14/1
+
+So for now on Linux/glibc, we fall back to the historical Unix version
+until we get glibc fixed.
+
+On some BSD variants, there is a issetugid() function. On other Unix
+variants, we fall back to what GTK+ has been doing.
+---
+ configure.ac | 15 ++++++++++++--
+ gio/gdbusaddress.c | 9 +++++++++
+ gio/gvfs.c | 3 +++
+ glib/genviron.c | 1 +
+ glib/glib-private.c | 4 +++-
+ glib/glib-private.h | 4 ++++
+ glib/gutils.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 7 files changed, 90 insertions(+), 3 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 584df1d..67ea1a9 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -583,9 +583,20 @@ AC_TRY_COMPILE([#include <dirent.h>], [DIR *dir;],
+ # Checks for library functions.
+ AC_FUNC_VPRINTF
+ AC_FUNC_ALLOCA
+-AC_CHECK_FUNCS(mmap posix_memalign memalign valloc fsync pipe2)
++AC_CHECK_FUNCS(mmap posix_memalign memalign valloc fsync pipe2 issetugid)
+ AC_CHECK_FUNCS(atexit on_exit timegm gmtime_r)
+
++AC_CACHE_CHECK([for __libc_enable_secure], glib_cv_have_libc_enable_secure,
++ [AC_TRY_LINK([#include <unistd.h>
++ extern int __libc_enable_secure;],
++ [return __libc_enable_secure;],
++ glib_cv_have_libc_enable_secure=yes,
++ glib_cv_have_libc_enable_secure=no)])
++AS_IF([test x$glib_cv_have_libc_enable_secure = xyes], [
++ AC_DEFINE(HAVE_LIBC_ENABLE_SECURE, 1,
++ [Define if you have the __libc_enable_secure variable (GNU libc, eglibc)])
++])
++
+ AC_CHECK_SIZEOF(char)
+ AC_CHECK_SIZEOF(short)
+ AC_CHECK_SIZEOF(long)
+@@ -984,7 +995,7 @@ AC_MSG_RESULT(unsigned $glib_size_type)
+
+ # Check for some functions
+ AC_CHECK_FUNCS(lstat strerror strsignal memmove vsnprintf stpcpy strcasecmp strncasecmp poll getcwd vasprintf setenv unsetenv getc_unlocked readlink symlink fdwalk memmem)
+-AC_CHECK_FUNCS(chown lchmod lchown fchmod fchown link utimes getgrgid getpwuid)
++AC_CHECK_FUNCS(chown lchmod lchown fchmod fchown link utimes getgrgid getpwuid getresuid)
+ AC_CHECK_FUNCS(getmntent_r setmntent endmntent hasmntopt getfsstat getvfsstat)
+ # Check for high-resolution sleep functions
+ AC_CHECK_FUNCS(splice)
+diff --git a/gio/gdbusaddress.c b/gio/gdbusaddress.c
+index 4aa13b9..96b6343 100644
+--- a/gio/gdbusaddress.c
++++ b/gio/gdbusaddress.c
+@@ -37,6 +37,7 @@
+ #include "giostream.h"
+ #include "gasyncresult.h"
+ #include "gsimpleasyncresult.h"
++#include "glib-private.h"
+ #include "gdbusprivate.h"
+ #include "giomodule-priv.h"
+ #include "gdbusdaemon.h"
+@@ -1023,6 +1024,14 @@ get_session_address_dbus_launch (GError **error)
+ restore_dbus_verbose = FALSE;
+ old_dbus_verbose = NULL;
+
++ /* Don't run binaries as root if we're setuid. */
++ if (GLIB_PRIVATE_CALL (g_check_setuid) ())
++ {
++ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
++ _("Cannot spawn a message bus when setuid"));
++ goto out;
++ }
++
+ machine_id = _g_dbus_get_machine_id (error);
+ if (machine_id == NULL)
+ {
+diff --git a/gio/gvfs.c b/gio/gvfs.c
+index dda8afb..9afbcec 100644
+--- a/gio/gvfs.c
++++ b/gio/gvfs.c
+@@ -23,6 +23,7 @@
+ #include "config.h"
+ #include <string.h>
+ #include "gvfs.h"
++#include "glib-private.h"
+ #include "glocalvfs.h"
+ #include "gresourcefile.h"
+ #include "giomodule-priv.h"
+@@ -191,6 +192,8 @@ g_vfs_parse_name (GVfs *vfs,
+ GVfs *
+ g_vfs_get_default (void)
+ {
++ if (GLIB_PRIVATE_CALL (g_check_setuid) ())
++ return g_vfs_get_local ();
+ return _g_io_module_get_default (G_VFS_EXTENSION_POINT_NAME,
+ "GIO_USE_VFS",
+ (GIOModuleVerifyFunc)g_vfs_is_active);
+diff --git a/glib/genviron.c b/glib/genviron.c
+index 59a8bbe..9525cf0 100644
+--- a/glib/genviron.c
++++ b/glib/genviron.c
+@@ -40,6 +40,7 @@
+ #include <windows.h>
+ #endif
+
++#include "glib-private.h"
+ #include "gmem.h"
+ #include "gmessages.h"
+ #include "gstrfuncs.h"
+diff --git a/glib/glib-private.c b/glib/glib-private.c
+index 3946e77..3506782 100644
+--- a/glib/glib-private.c
++++ b/glib/glib-private.c
+@@ -38,7 +38,9 @@ glib__private__ (void)
+ g_wakeup_signal,
+ g_wakeup_acknowledge,
+
+- g_get_worker_context
++ g_get_worker_context,
++
++ g_check_setuid
+ };
+
+ return &table;
+diff --git a/glib/glib-private.h b/glib/glib-private.h
+index fde0be8..87da6f3 100644
+--- a/glib/glib-private.h
++++ b/glib/glib-private.h
+@@ -25,6 +25,8 @@
+
+ G_GNUC_INTERNAL
+ GMainContext * g_get_worker_context (void);
++G_GNUC_INTERNAL
++gboolean g_check_setuid (void);
+
+ #define GLIB_PRIVATE_CALL(symbol) (glib__private__()->symbol)
+
+@@ -40,6 +42,8 @@ typedef struct {
+ /* See gmain.c */
+ GMainContext * (* g_get_worker_context) (void);
+ /* Add other private functions here, initialize them in glib-private.c */
++
++ gboolean (* g_check_setuid) (void);
+ } GLibPrivateVTable;
+
+ GLibPrivateVTable *glib__private__ (void);
+diff --git a/glib/gutils.c b/glib/gutils.c
+index 38b5e44..f8a38d1 100644
+--- a/glib/gutils.c
++++ b/glib/gutils.c
+@@ -2409,3 +2409,60 @@ g_get_tmp_dir (void)
+ }
+
+ #endif
++
++/* Private API:
++ *
++ * Returns %TRUE if the current process was executed as setuid (or an
++ * equivalent __libc_enable_secure is available). See:
++ * http://osdir.com/ml/linux.lfs.hardened/2007-04/msg00032.html
++ */
++gboolean
++g_check_setuid (void)
++{
++ /* TODO: get __libc_enable_secure exported from glibc.
++ * See http://www.openwall.com/lists/owl-dev/2012/08/14/1
++ */
++#if 0 && defined(HAVE_LIBC_ENABLE_SECURE)
++ {
++ /* See glibc/include/unistd.h */
++ extern int __libc_enable_secure;
++ return __libc_enable_secure;
++ }
++#elif defined(HAVE_ISSETUGID)
++ /* BSD: http://www.freebsd.org/cgi/man.cgi?query=issetugid&sektion=2 */
++ return issetugid ();
++#elif defined(G_OS_UNIX)
++ uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
++ gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
++
++ static gsize check_setuid_initialised;
++ static gboolean is_setuid;
++
++ if (g_once_init_enter (&check_setuid_initialised))
++ {
++#ifdef HAVE_GETRESUID
++ /* These aren't in the header files, so we prototype them here.
++ */
++ int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
++ int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
++
++ if (getresuid (&ruid, &euid, &suid) != 0 ||
++ getresgid (&rgid, &egid, &sgid) != 0)
++#endif /* HAVE_GETRESUID */
++ {
++ suid = ruid = getuid ();
++ sgid = rgid = getgid ();
++ euid = geteuid ();
++ egid = getegid ();
++ }
++
++ is_setuid = (ruid != euid || ruid != suid ||
++ rgid != egid || rgid != sgid);
++
++ g_once_init_leave (&check_setuid_initialised, 1);
++ }
++ return is_setuid;
++#else
++ return FALSE;
++#endif
++}
+--
+1.7.11.4
+
diff --git a/glib2.spec b/glib2.spec
index c4d7e63..92d94f3 100644
--- a/glib2.spec
+++ b/glib2.spec
@@ -1,13 +1,15 @@
Summary: A library of handy utility functions
Name: glib2
Version: 2.32.4
-Release: 1%{?dist}
+Release: 2%{?dist}
License: LGPLv2+
Group: System Environment/Libraries
URL: http://www.gtk.org
#VCS: git:git://git.gnome.org/glib
Source: http://download.gnome.org/sources/glib/2.32/glib-%{version}.tar.xz
+Patch0: 0001-CVE-2012-3524-Hardening-for-being-run-in-a-setuid-en.patch
+
BuildRequires: pkgconfig
BuildRequires: gamin-devel
BuildRequires: gettext
@@ -56,6 +58,7 @@ The glib2-static package includes static libraries of the GLib library.
%prep
%setup -q -n glib-%{version}
+%patch0 -p1
%build
# Support builds of both git snapshots and tarballs packed with autogoo
@@ -157,6 +160,10 @@ gio-querymodules-%{__isa_bits} %{_libdir}/gio/modules
%{_libdir}/lib*.a
%changelog
+* Thu Sep 13 2012 Colin Walters <walters at verbum.org> - 2.32.4-2
+- CVE-2012-3524
+- Resolves: #857226
+
* Sat Jul 14 2012 Matthias Clasen <mclasen at redhat.com> 2.32.4-1
- Update to 2.32.4
More information about the scm-commits
mailing list