summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS12
-rw-r--r--aclocal.m47
-rw-r--r--bus/activation.c28
-rw-r--r--bus/bus.c50
-rw-r--r--bus/bus.h1
-rwxr-xr-xconfigure30
-rw-r--r--configure.ac4
-rw-r--r--dbus/dbus-sysdeps-util-unix.c145
-rw-r--r--dbus/dbus-sysdeps-util-win.c35
-rw-r--r--dbus/dbus-sysdeps.h11
-rw-r--r--doc/Makefile.in2
11 files changed, 260 insertions, 65 deletions
diff --git a/NEWS b/NEWS
index b10ab4f7..aa821fe1 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,15 @@
+D-Bus 1.8.10 (2014-11-10)
+==
+
+The “tenants with a leaking roof get priority” release.
+
+Security fixes:
+
+• Increase dbus-daemon's RLIMIT_NOFILE rlimit to 65536
+ so that CVE-2014-3636 part A cannot exhaust the system bus'
+ file descriptors, completing the incomplete fix in 1.8.8.
+ (CVE-2014-7824, fd.o #85105; Simon McVittie, Alban Crequy)
+
D-Bus 1.8.8 (2014-09-16)
==
diff --git a/aclocal.m4 b/aclocal.m4
index e02ecf9e..c2c4011e 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -103,10 +103,9 @@ _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
# configured tree to be moved without reconfiguration.
AC_DEFUN([AM_AUX_DIR_EXPAND],
-[dnl Rely on autoconf to set up CDPATH properly.
-AC_PREREQ([2.50])dnl
-# expand $ac_aux_dir to an absolute path
-am_aux_dir=`cd $ac_aux_dir && pwd`
+[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
+# Expand $ac_aux_dir to an absolute path.
+am_aux_dir=`cd "$ac_aux_dir" && pwd`
])
# AM_CONDITIONAL -*- Autoconf -*-
diff --git a/bus/activation.c b/bus/activation.c
index 149cca8a..ecd19bb4 100644
--- a/bus/activation.c
+++ b/bus/activation.c
@@ -1688,6 +1688,31 @@ out:
return retval;
}
+static void
+child_setup (void *user_data)
+{
+#ifdef DBUS_UNIX
+ BusActivation *activation = user_data;
+ DBusRLimit *initial_fd_limit;
+ DBusError error;
+
+ dbus_error_init (&error);
+ initial_fd_limit = bus_context_get_initial_fd_limit (activation->context);
+
+ if (initial_fd_limit != NULL &&
+ !_dbus_rlimit_restore_fd_limit (initial_fd_limit, &error))
+ {
+ /* unfortunately we don't actually know the service name here */
+ bus_context_log (activation->context,
+ DBUS_SYSTEM_LOG_INFO,
+ "Failed to reset fd limit before activating "
+ "service: %s: %s",
+ error.name, error.message);
+ }
+#endif
+}
+
+
dbus_bool_t
bus_activation_activate_service (BusActivation *activation,
DBusConnection *connection,
@@ -2121,7 +2146,8 @@ bus_activation_activate_service (BusActivation *activation,
service_name,
argv,
envp,
- NULL, activation,
+ child_setup,
+ activation,
&tmp_error))
{
_dbus_verbose ("Failed to spawn child\n");
diff --git a/bus/bus.c b/bus/bus.c
index 35d40754..47cc3452 100644
--- a/bus/bus.c
+++ b/bus/bus.c
@@ -64,6 +64,7 @@ struct BusContext
BusPolicy *policy;
BusMatchmaker *matchmaker;
BusLimits limits;
+ DBusRLimit *initial_fd_limit;
unsigned int fork : 1;
unsigned int syslog : 1;
unsigned int keep_umask : 1;
@@ -659,19 +660,38 @@ oom:
static void
raise_file_descriptor_limit (BusContext *context)
{
+#ifdef DBUS_UNIX
+ DBusError error = DBUS_ERROR_INIT;
- /* I just picked this out of thin air; we need some extra
- * descriptors for things like any internal pipes we create,
- * inotify, connections to SELinux, etc.
- */
- unsigned int arbitrary_extra_fds = 32;
- unsigned int limit;
+ /* we only do this once */
+ if (context->initial_fd_limit != NULL)
+ return;
- limit = context->limits.max_completed_connections +
- context->limits.max_incomplete_connections
- + arbitrary_extra_fds;
+ context->initial_fd_limit = _dbus_rlimit_save_fd_limit (&error);
+
+ if (context->initial_fd_limit == NULL)
+ {
+ bus_context_log (context, DBUS_SYSTEM_LOG_INFO,
+ "%s: %s", error.name, error.message);
+ dbus_error_free (&error);
+ return;
+ }
- _dbus_request_file_descriptor_limit (limit);
+ /* We used to compute a suitable rlimit based on the configured number
+ * of connections, but that breaks down as soon as we allow fd-passing,
+ * because each connection is allowed to pass 64 fds to us, and if
+ * they all did, we'd hit kernel limits. We now hard-code 64k as a
+ * good limit, like systemd does: that's enough to avoid DoS from
+ * anything short of multiple uids conspiring against us.
+ */
+ if (!_dbus_rlimit_raise_fd_limit_if_privileged (65536, &error))
+ {
+ bus_context_log (context, DBUS_SYSTEM_LOG_INFO,
+ "%s: %s", error.name, error.message);
+ dbus_error_free (&error);
+ return;
+ }
+#endif
}
static dbus_bool_t
@@ -1130,6 +1150,10 @@ bus_context_unref (BusContext *context)
dbus_free (context->pidfile);
}
+
+ if (context->initial_fd_limit)
+ _dbus_rlimit_free (context->initial_fd_limit);
+
dbus_free (context);
dbus_server_free_data_slot (&server_data_slot);
@@ -1294,6 +1318,12 @@ bus_context_get_reply_timeout (BusContext *context)
return context->limits.reply_timeout;
}
+DBusRLimit *
+bus_context_get_initial_fd_limit (BusContext *context)
+{
+ return context->initial_fd_limit;
+}
+
void
bus_context_log (BusContext *context, DBusSystemLogSeverity severity, const char *msg, ...) _DBUS_GNUC_PRINTF (3, 4);
diff --git a/bus/bus.h b/bus/bus.h
index 7d0b3697..dac6ea5e 100644
--- a/bus/bus.h
+++ b/bus/bus.h
@@ -116,6 +116,7 @@ int bus_context_get_max_services_per_connection (BusContext
int bus_context_get_max_match_rules_per_connection (BusContext *context);
int bus_context_get_max_replies_per_connection (BusContext *context);
int bus_context_get_reply_timeout (BusContext *context);
+DBusRLimit * bus_context_get_initial_fd_limit (BusContext *context);
void bus_context_log (BusContext *context,
DBusSystemLogSeverity severity,
const char *msg,
diff --git a/configure b/configure
index fb0d5176..87e5d5b3 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for dbus 1.8.8.
+# Generated by GNU Autoconf 2.69 for dbus 1.8.10.
#
# Report bugs to <https://bugs.freedesktop.org/enter_bug.cgi?product=dbus>.
#
@@ -591,8 +591,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='dbus'
PACKAGE_TARNAME='dbus'
-PACKAGE_VERSION='1.8.8'
-PACKAGE_STRING='dbus 1.8.8'
+PACKAGE_VERSION='1.8.10'
+PACKAGE_STRING='dbus 1.8.10'
PACKAGE_BUGREPORT='https://bugs.freedesktop.org/enter_bug.cgi?product=dbus'
PACKAGE_URL=''
@@ -1513,7 +1513,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures dbus 1.8.8 to adapt to many kinds of systems.
+\`configure' configures dbus 1.8.10 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1587,7 +1587,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of dbus 1.8.8:";;
+ short | recursive ) echo "Configuration of dbus 1.8.10:";;
esac
cat <<\_ACEOF
@@ -1784,7 +1784,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-dbus configure 1.8.8
+dbus configure 1.8.10
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2503,7 +2503,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by dbus $as_me 1.8.8, which was
+It was created by dbus $as_me 1.8.10, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -3132,8 +3132,8 @@ test "$program_suffix" != NONE &&
ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
-# expand $ac_aux_dir to an absolute path
-am_aux_dir=`cd $ac_aux_dir && pwd`
+# Expand $ac_aux_dir to an absolute path.
+am_aux_dir=`cd "$ac_aux_dir" && pwd`
if test x"${MISSING+set}" != xset; then
case $am_aux_dir in
@@ -3446,7 +3446,7 @@ fi
# Define the identity of the package.
PACKAGE='dbus'
- VERSION='1.8.8'
+ VERSION='1.8.10'
cat >>confdefs.h <<_ACEOF
@@ -3746,7 +3746,7 @@ LT_CURRENT=11
## increment any time the source changes; set to
## 0 if you increment CURRENT
-LT_REVISION=7
+LT_REVISION=8
## increment if any interfaces have been added; set to 0
## if any interfaces have been changed or removed. removal has
@@ -3759,8 +3759,8 @@ LT_AGE=8
DBUS_MAJOR_VERSION=1
DBUS_MINOR_VERSION=8
-DBUS_MICRO_VERSION=8
-DBUS_VERSION=1.8.8
+DBUS_MICRO_VERSION=10
+DBUS_VERSION=1.8.10
@@ -23428,7 +23428,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by dbus $as_me 1.8.8, which was
+This file was extended by dbus $as_me 1.8.10, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -23494,7 +23494,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-dbus config.status 1.8.8
+dbus config.status 1.8.10
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index 2d4624c7..df32f238 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3,7 +3,7 @@ AC_PREREQ([2.63])
m4_define([dbus_major_version], [1])
m4_define([dbus_minor_version], [8])
-m4_define([dbus_micro_version], [8])
+m4_define([dbus_micro_version], [10])
m4_define([dbus_version],
[dbus_major_version.dbus_minor_version.dbus_micro_version])
AC_INIT([dbus],[dbus_version],[https://bugs.freedesktop.org/enter_bug.cgi?product=dbus],[dbus])
@@ -37,7 +37,7 @@ LT_CURRENT=11
## increment any time the source changes; set to
## 0 if you increment CURRENT
-LT_REVISION=7
+LT_REVISION=8
## increment if any interfaces have been added; set to 0
## if any interfaces have been changed or removed. removal has
diff --git a/dbus/dbus-sysdeps-util-unix.c b/dbus/dbus-sysdeps-util-unix.c
index 0d8a66c7..199eb3dd 100644
--- a/dbus/dbus-sysdeps-util-unix.c
+++ b/dbus/dbus-sysdeps-util-unix.c
@@ -378,53 +378,140 @@ _dbus_change_to_daemon_user (const char *user,
}
#endif /* !HAVE_LIBAUDIT */
+#ifdef HAVE_SETRLIMIT
-/**
- * Attempt to ensure that the current process can open
- * at least @p limit file descriptors.
- *
- * If @p limit is lower than the current, it will not be
- * lowered. No error is returned if the request can
- * not be satisfied.
- *
- * @param limit number of file descriptors
+/* We assume that if we have setrlimit, we also have getrlimit and
+ * struct rlimit.
*/
-void
-_dbus_request_file_descriptor_limit (unsigned int limit)
+
+struct DBusRLimit {
+ struct rlimit lim;
+};
+
+DBusRLimit *
+_dbus_rlimit_save_fd_limit (DBusError *error)
+{
+ DBusRLimit *self;
+
+ self = dbus_new0 (DBusRLimit, 1);
+
+ if (self == NULL)
+ {
+ _DBUS_SET_OOM (error);
+ return NULL;
+ }
+
+ if (getrlimit (RLIMIT_NOFILE, &self->lim) < 0)
+ {
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "Failed to get fd limit: %s", _dbus_strerror (errno));
+ dbus_free (self);
+ return NULL;
+ }
+
+ return self;
+}
+
+dbus_bool_t
+_dbus_rlimit_raise_fd_limit_if_privileged (unsigned int desired,
+ DBusError *error)
{
-#ifdef HAVE_SETRLIMIT
struct rlimit lim;
- struct rlimit target_lim;
/* No point to doing this practically speaking
* if we're not uid 0. We expect the system
* bus to use this before we change UID, and
- * the session bus takes the Linux default
- * of 1024 for both cur and max.
+ * the session bus takes the Linux default,
+ * currently 1024 for cur and 4096 for max.
*/
if (getuid () != 0)
- return;
+ {
+ /* not an error, we're probably the session bus */
+ return TRUE;
+ }
if (getrlimit (RLIMIT_NOFILE, &lim) < 0)
- return;
+ {
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "Failed to get fd limit: %s", _dbus_strerror (errno));
+ return FALSE;
+ }
- if (lim.rlim_cur >= limit)
- return;
+ if (lim.rlim_cur == RLIM_INFINITY || lim.rlim_cur >= desired)
+ {
+ /* not an error, everything is fine */
+ return TRUE;
+ }
/* Ignore "maximum limit", assume we have the "superuser"
* privileges. On Linux this is CAP_SYS_RESOURCE.
*/
- target_lim.rlim_cur = target_lim.rlim_max = limit;
- /* Also ignore errors; if we fail, we will at least work
- * up to whatever limit we had, which seems better than
- * just outright aborting.
- *
- * However, in the future we should probably log this so OS builders
- * have a chance to notice any misconfiguration like dbus-daemon
- * being started without CAP_SYS_RESOURCE.
- */
- setrlimit (RLIMIT_NOFILE, &target_lim);
+ lim.rlim_cur = lim.rlim_max = desired;
+
+ if (setrlimit (RLIMIT_NOFILE, &lim) < 0)
+ {
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "Failed to set fd limit to %u: %s",
+ desired, _dbus_strerror (errno));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+dbus_bool_t
+_dbus_rlimit_restore_fd_limit (DBusRLimit *saved,
+ DBusError *error)
+{
+ if (setrlimit (RLIMIT_NOFILE, &saved->lim) < 0)
+ {
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "Failed to restore old fd limit: %s",
+ _dbus_strerror (errno));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+#else /* !HAVE_SETRLIMIT */
+
+static void
+fd_limit_not_supported (DBusError *error)
+{
+ dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
+ "cannot change fd limit on this platform");
+}
+
+DBusRLimit *
+_dbus_rlimit_save_fd_limit (DBusError *error)
+{
+ fd_limit_not_supported (error);
+ return NULL;
+}
+
+dbus_bool_t
+_dbus_rlimit_raise_fd_limit_if_privileged (unsigned int desired,
+ DBusError *error)
+{
+ fd_limit_not_supported (error);
+ return FALSE;
+}
+
+dbus_bool_t
+_dbus_rlimit_restore_fd_limit (DBusRLimit *saved,
+ DBusError *error)
+{
+ fd_limit_not_supported (error);
+ return FALSE;
+}
+
#endif
+
+void
+_dbus_rlimit_free (DBusRLimit *lim)
+{
+ dbus_free (lim);
}
void
diff --git a/dbus/dbus-sysdeps-util-win.c b/dbus/dbus-sysdeps-util-win.c
index 4678b11e..ec9afbb6 100644
--- a/dbus/dbus-sysdeps-util-win.c
+++ b/dbus/dbus-sysdeps-util-win.c
@@ -258,9 +258,42 @@ _dbus_change_to_daemon_user (const char *user,
return TRUE;
}
+static void
+fd_limit_not_supported (DBusError *error)
+{
+ dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
+ "cannot change fd limit on this platform");
+}
+
+DBusRLimit *
+_dbus_rlimit_save_fd_limit (DBusError *error)
+{
+ fd_limit_not_supported (error);
+ return NULL;
+}
+
+dbus_bool_t
+_dbus_rlimit_raise_fd_limit_if_privileged (unsigned int desired,
+ DBusError *error)
+{
+ fd_limit_not_supported (error);
+ return FALSE;
+}
+
+dbus_bool_t
+_dbus_rlimit_restore_fd_limit (DBusRLimit *saved,
+ DBusError *error)
+{
+ fd_limit_not_supported (error);
+ return FALSE;
+}
+
void
-_dbus_request_file_descriptor_limit (unsigned int limit)
+_dbus_rlimit_free (DBusRLimit *lim)
{
+ /* _dbus_rlimit_save_fd_limit() cannot return non-NULL on Windows
+ * so there cannot be anything to free */
+ _dbus_assert (lim == NULL);
}
void
diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h
index 47ba2f43..5465128e 100644
--- a/dbus/dbus-sysdeps.h
+++ b/dbus/dbus-sysdeps.h
@@ -546,8 +546,6 @@ dbus_bool_t _dbus_change_to_daemon_user (const char *user,
void _dbus_flush_caches (void);
-void _dbus_request_file_descriptor_limit (unsigned int limit);
-
/*
* replaces the term DBUS_PREFIX in configure_time_path by the
* current dbus installation directory. On unix this function is a noop
@@ -566,6 +564,15 @@ _dbus_replace_install_prefix (const char *configure_time_path);
*/
#define DBUS_DEFAULT_MESSAGE_UNIX_FDS 16
+typedef struct DBusRLimit DBusRLimit;
+
+DBusRLimit *_dbus_rlimit_save_fd_limit (DBusError *error);
+dbus_bool_t _dbus_rlimit_raise_fd_limit_if_privileged (unsigned int desired,
+ DBusError *error);
+dbus_bool_t _dbus_rlimit_restore_fd_limit (DBusRLimit *saved,
+ DBusError *error);
+void _dbus_rlimit_free (DBusRLimit *lim);
+
/** @} */
DBUS_END_DECLS
diff --git a/doc/Makefile.in b/doc/Makefile.in
index a48c7e5a..23e3802b 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -666,8 +666,8 @@ distclean-generic:
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-@DBUS_DOXYGEN_DOCS_ENABLED_FALSE@install-data-local:
@DBUS_DOXYGEN_DOCS_ENABLED_FALSE@uninstall-local:
+@DBUS_DOXYGEN_DOCS_ENABLED_FALSE@install-data-local:
clean: clean-am
clean-am: clean-generic clean-libtool clean-local mostlyclean-am