diff options
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | dbus/dbus-keyring.c | 7 | ||||
-rw-r--r-- | dbus/dbus-sysdeps-unix.c | 74 | ||||
-rw-r--r-- | dbus/dbus-sysdeps-win.c | 6 | ||||
-rw-r--r-- | dbus/dbus-sysdeps.c | 5 | ||||
-rw-r--r-- | dbus/dbus-sysdeps.h | 1 |
6 files changed, 94 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac index e2c9bdf7..b0f2ec20 100644 --- a/configure.ac +++ b/configure.ac @@ -595,7 +595,7 @@ AC_DEFINE_UNQUOTED([DBUS_USE_SYNC], [$have_sync], [Use the gcc __sync extension] AC_SEARCH_LIBS(socket,[socket network]) AC_CHECK_FUNC(gethostbyname,,[AC_CHECK_LIB(nsl,gethostbyname)]) -AC_CHECK_FUNCS(vsnprintf vasprintf nanosleep usleep setenv clearenv unsetenv socketpair getgrouplist fpathconf setrlimit poll setlocale localeconv strtoll strtoull) +AC_CHECK_FUNCS(vsnprintf vasprintf nanosleep usleep setenv clearenv unsetenv socketpair getgrouplist fpathconf setrlimit poll setlocale localeconv strtoll strtoull issetugid getresuid) AC_CHECK_HEADERS([syslog.h]) if test "x$ac_cv_header_syslog_h" = "xyes"; then diff --git a/dbus/dbus-keyring.c b/dbus/dbus-keyring.c index 23b9df5a..3b9ce315 100644 --- a/dbus/dbus-keyring.c +++ b/dbus/dbus-keyring.c @@ -717,6 +717,13 @@ _dbus_keyring_new_for_credentials (DBusCredentials *credentials, DBusCredentials *our_credentials; _DBUS_ASSERT_ERROR_IS_CLEAR (error); + + if (_dbus_check_setuid ()) + { + dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, + "Unable to create DBus keyring when setuid"); + return NULL; + } keyring = NULL; error_set = FALSE; diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c index cef8bd31..b4ecc96e 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -3434,6 +3434,13 @@ _dbus_get_autolaunch_address (const char *scope, DBusString uuid; dbus_bool_t retval; + if (_dbus_check_setuid ()) + { + dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, + "Unable to autolaunch when setuid"); + return FALSE; + } + _DBUS_ASSERT_ERROR_IS_CLEAR (error); retval = FALSE; @@ -3551,6 +3558,13 @@ _dbus_lookup_launchd_socket (DBusString *socket_path, _DBUS_ASSERT_ERROR_IS_CLEAR (error); + if (_dbus_check_setuid ()) + { + dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, + "Unable to find launchd socket when setuid"); + return FALSE; + } + i = 0; argv[i] = "launchctl"; ++i; @@ -3591,6 +3605,13 @@ _dbus_lookup_session_address_launchd (DBusString *address, DBusError *error) dbus_bool_t valid_socket; DBusString socket_path; + if (_dbus_check_setuid ()) + { + dbus_set_error_const (error, DBUS_ERROR_NOT_SUPPORTED, + "Unable to find launchd socket when setuid"); + return FALSE; + } + if (!_dbus_string_init (&socket_path)) { _DBUS_SET_OOM (error); @@ -4086,4 +4107,57 @@ _dbus_close_all (void) close (i); } +/** + * **NOTE**: If you modify this function, please also consider making + * the corresponding change in GLib. See + * glib/gutils.c:g_check_setuid(). + * + * 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 + */ +dbus_bool_t +_dbus_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 (); +#else + 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 dbus_bool_t check_setuid_initialised; + static dbus_bool_t is_setuid; + + if (_DBUS_UNLIKELY (!check_setuid_initialised)) + { +#ifdef HAVE_GETRESUID + if (getresuid (&ruid, &euid, &suid) != 0 || + getresgid (&rgid, &egid, &sgid) != 0) +#endif /* HAVE_GETRESUID */ + { + suid = ruid = getuid (); + sgid = rgid = getgid (); + euid = geteuid (); + egid = getegid (); + } + + check_setuid_initialised = TRUE; + is_setuid = (ruid != euid || ruid != suid || + rgid != egid || rgid != sgid); + + } + return is_setuid; +#endif +} + /* tests in dbus-sysdeps-util.c */ diff --git a/dbus/dbus-sysdeps-win.c b/dbus/dbus-sysdeps-win.c index 397520af..bc4951b5 100644 --- a/dbus/dbus-sysdeps-win.c +++ b/dbus/dbus-sysdeps-win.c @@ -3632,6 +3632,12 @@ _dbus_path_is_absolute (const DBusString *filename) return FALSE; } +dbus_bool_t +_dbus_check_setuid (void) +{ + return FALSE; +} + /** @} end of sysdeps-win */ /* tests in dbus-sysdeps-util.c */ diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c index 861bfec9..04fb8d76 100644 --- a/dbus/dbus-sysdeps.c +++ b/dbus/dbus-sysdeps.c @@ -182,6 +182,11 @@ _dbus_setenv (const char *varname, const char* _dbus_getenv (const char *varname) { + /* Don't respect any environment variables if the current process is + * setuid. This is the equivalent of glibc's __secure_getenv(). + */ + if (_dbus_check_setuid ()) + return NULL; return getenv (varname); } diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h index 4052cda9..eee91608 100644 --- a/dbus/dbus-sysdeps.h +++ b/dbus/dbus-sysdeps.h @@ -87,6 +87,7 @@ typedef struct DBusPipe DBusPipe; void _dbus_abort (void) _DBUS_GNUC_NORETURN; +dbus_bool_t _dbus_check_setuid (void); const char* _dbus_getenv (const char *varname); dbus_bool_t _dbus_setenv (const char *varname, const char *value); |