Your message dated Wed, 12 Nov 2014 14:49:12 +0100 with message-id <20141112134912.GW2077@betterave.cristau.org> and subject line Re: Bug#768992: unblock: dbus/1.8.10-1 has caused the Debian Bug report #768992, regarding unblock: dbus/1.8.10-1 to be marked as done. This means that you claim that the problem has been dealt with. If this is not the case it is now your responsibility to reopen the Bug report if necessary, and/or fix the problem forthwith. (NB: If you are a system administrator and have no idea what this message is talking about, this may indicate a serious mail system misconfiguration somewhere. Please contact owner@bugs.debian.org immediately.) -- 768992: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=768992 Debian Bug Tracking System Contact owner@bugs.debian.org with problems
--- Begin Message ---
- To: Debian Bug Tracking System <submit@bugs.debian.org>
- Subject: unblock: dbus/1.8.10-1
- From: Simon McVittie <smcv@debian.org>
- Date: Mon, 10 Nov 2014 16:28:28 +0000
- Message-id: <[🔎] 20141110162828.GA28555@reptile.pseudorandom.co.uk>
Package: release.debian.org Severity: normal User: release.debian.org@packages.debian.org Usertags: unblock Please unblock package dbus to pick up the denial of service fix that I just released (CVE-2014-7824): unblock dbus/1.8.10-1 The new upstream release does not introduce any changes other than the security fix and the new version metadata, so I imported it as-is rather than doing a trivial "backport". I attach a filtered source debdiff with autotools noise excluded (we re-generate the autotools files with autoreconf during the build anyway), and a full source debdiff. Thanks, Sdiffstat for dbus-1.8.8 dbus-1.8.10 NEWS | 12 +++ aclocal.m4 | 7 -- bus/activation.c | 28 +++++++- bus/bus.c | 50 +++++++++++--- bus/bus.h | 1 configure | 30 ++++---- configure.ac | 4 - dbus/dbus-sysdeps-util-unix.c | 147 +++++++++++++++++++++++++++++++++--------- dbus/dbus-sysdeps-util-win.c | 35 +++++++++- dbus/dbus-sysdeps.h | 11 ++- debian/changelog | 12 +++ debian/dbus.init | 2 doc/Makefile.in | 2 13 files changed, 274 insertions(+), 67 deletions(-) diff -Nru dbus-1.8.8/aclocal.m4 dbus-1.8.10/aclocal.m4 --- dbus-1.8.8/aclocal.m4 2014-09-15 12:43:13.000000000 +0100 +++ dbus-1.8.10/aclocal.m4 2014-11-06 15:40:17.000000000 +0000 @@ -103,10 +103,9 @@ # 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 -Nru dbus-1.8.8/bus/activation.c dbus-1.8.10/bus/activation.c --- dbus-1.8.8/bus/activation.c 2014-09-12 12:52:11.000000000 +0100 +++ dbus-1.8.10/bus/activation.c 2014-11-06 15:30:51.000000000 +0000 @@ -1688,6 +1688,31 @@ 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 @@ service_name, argv, envp, - NULL, activation, + child_setup, + activation, &tmp_error)) { _dbus_verbose ("Failed to spawn child\n"); diff -Nru dbus-1.8.8/bus/bus.c dbus-1.8.10/bus/bus.c --- dbus-1.8.8/bus/bus.c 2014-09-15 12:29:28.000000000 +0100 +++ dbus-1.8.10/bus/bus.c 2014-11-06 15:30:51.000000000 +0000 @@ -64,6 +64,7 @@ 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 @@ 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); - _dbus_request_file_descriptor_limit (limit); + 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; + } + + /* 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 @@ 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 @@ 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 -Nru dbus-1.8.8/bus/bus.h dbus-1.8.10/bus/bus.h --- dbus-1.8.8/bus/bus.h 2014-09-15 12:29:28.000000000 +0100 +++ dbus-1.8.10/bus/bus.h 2014-11-04 15:04:06.000000000 +0000 @@ -116,6 +116,7 @@ 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 -Nru dbus-1.8.8/configure dbus-1.8.10/configure --- dbus-1.8.8/configure 2014-09-15 12:43:15.000000000 +0100 +++ dbus-1.8.10/configure 2014-11-06 15:40:18.000000000 +0000 @@ -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 @@ # 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 @@ # 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ # Define the identity of the package. PACKAGE='dbus' - VERSION='1.8.8' + VERSION='1.8.10' cat >>confdefs.h <<_ACEOF @@ -3746,7 +3746,7 @@ ## 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 @@ 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 @@ # 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 @@ 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 -Nru dbus-1.8.8/configure.ac dbus-1.8.10/configure.ac --- dbus-1.8.8/configure.ac 2014-09-15 12:42:50.000000000 +0100 +++ dbus-1.8.10/configure.ac 2014-11-06 15:34:45.000000000 +0000 @@ -3,7 +3,7 @@ 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 @@ ## 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 -Nru dbus-1.8.8/dbus/dbus-sysdeps.h dbus-1.8.10/dbus/dbus-sysdeps.h --- dbus-1.8.8/dbus/dbus-sysdeps.h 2014-09-15 12:27:24.000000000 +0100 +++ dbus-1.8.10/dbus/dbus-sysdeps.h 2014-11-06 15:30:51.000000000 +0000 @@ -546,8 +546,6 @@ 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 @@ */ #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 -Nru dbus-1.8.8/dbus/dbus-sysdeps-util-unix.c dbus-1.8.10/dbus/dbus-sysdeps-util-unix.c --- dbus-1.8.8/dbus/dbus-sysdeps-util-unix.c 2014-09-12 12:52:11.000000000 +0100 +++ dbus-1.8.10/dbus/dbus-sysdeps-util-unix.c 2014-11-06 15:30:51.000000000 +0000 @@ -378,53 +378,140 @@ } #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; - - if (lim.rlim_cur >= limit) - 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 == 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 -Nru dbus-1.8.8/dbus/dbus-sysdeps-util-win.c dbus-1.8.10/dbus/dbus-sysdeps-util-win.c --- dbus-1.8.8/dbus/dbus-sysdeps-util-win.c 2014-09-12 12:52:11.000000000 +0100 +++ dbus-1.8.10/dbus/dbus-sysdeps-util-win.c 2014-11-06 15:30:51.000000000 +0000 @@ -258,9 +258,42 @@ 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 -Nru dbus-1.8.8/debian/changelog dbus-1.8.10/debian/changelog --- dbus-1.8.8/debian/changelog 2014-10-06 19:17:12.000000000 +0100 +++ dbus-1.8.10/debian/changelog 2014-11-06 16:28:35.000000000 +0000 @@ -1,3 +1,15 @@ +dbus (1.8.10-1) unstable; urgency=medium + + * New upstream release 1.8.10 + - raise dbus-daemon's file descriptor limit to 65536 to avoid an + opportunity for denial of service + (CVE-2014-7824, an incomplete fix for CVE-2014-3636) + * Start 'dbus-daemon --system' as root under sysvinit (it already + starts as root under systemd), so it can increase its file + descriptor limit + + -- Simon McVittie <smcv@debian.org> Thu, 06 Nov 2014 16:28:22 +0000 + dbus (1.8.8-2) unstable; urgency=medium [ Michael Biebl ] diff -Nru dbus-1.8.8/debian/dbus.init dbus-1.8.10/debian/dbus.init --- dbus-1.8.8/debian/dbus.init 2014-10-06 19:17:12.000000000 +0100 +++ dbus-1.8.10/debian/dbus.init 2014-11-06 16:28:35.000000000 +0000 @@ -69,7 +69,7 @@ log_daemon_msg "Starting $DESC" "$NAME" start-stop-daemon --start --quiet --pidfile $PIDFILE \ - --user $DAEMONUSER --exec $DAEMON -- --system $PARAMS + --exec $DAEMON -- --system $PARAMS log_end_msg $? } diff -Nru dbus-1.8.8/doc/Makefile.in dbus-1.8.10/doc/Makefile.in --- dbus-1.8.8/doc/Makefile.in 2014-09-15 12:43:15.000000000 +0100 +++ dbus-1.8.10/doc/Makefile.in 2014-11-06 15:40:19.000000000 +0000 @@ -666,8 +666,8 @@ 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 diff -Nru dbus-1.8.8/NEWS dbus-1.8.10/NEWS --- dbus-1.8.8/NEWS 2014-09-15 12:42:33.000000000 +0100 +++ dbus-1.8.10/NEWS 2014-11-06 15:39:02.000000000 +0000 @@ -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) ==diffstat for dbus-1.8.8 dbus-1.8.10 NEWS | 12 +++ bus/activation.c | 28 +++++++- bus/bus.c | 50 +++++++++++--- bus/bus.h | 1 configure.ac | 4 - dbus/dbus-sysdeps-util-unix.c | 147 +++++++++++++++++++++++++++++++++--------- dbus/dbus-sysdeps-util-win.c | 35 +++++++++- dbus/dbus-sysdeps.h | 11 ++- debian/changelog | 12 +++ debian/dbus.init | 2 10 files changed, 255 insertions(+), 47 deletions(-) diff -Nru --exclude aclocal.m4 --exclude configure --exclude Makefile.in dbus-1.8.8/bus/activation.c dbus-1.8.10/bus/activation.c --- dbus-1.8.8/bus/activation.c 2014-09-12 12:52:11.000000000 +0100 +++ dbus-1.8.10/bus/activation.c 2014-11-06 15:30:51.000000000 +0000 @@ -1688,6 +1688,31 @@ 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 @@ service_name, argv, envp, - NULL, activation, + child_setup, + activation, &tmp_error)) { _dbus_verbose ("Failed to spawn child\n"); diff -Nru --exclude aclocal.m4 --exclude configure --exclude Makefile.in dbus-1.8.8/bus/bus.c dbus-1.8.10/bus/bus.c --- dbus-1.8.8/bus/bus.c 2014-09-15 12:29:28.000000000 +0100 +++ dbus-1.8.10/bus/bus.c 2014-11-06 15:30:51.000000000 +0000 @@ -64,6 +64,7 @@ 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 @@ 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); - _dbus_request_file_descriptor_limit (limit); + 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; + } + + /* 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 @@ 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 @@ 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 -Nru --exclude aclocal.m4 --exclude configure --exclude Makefile.in dbus-1.8.8/bus/bus.h dbus-1.8.10/bus/bus.h --- dbus-1.8.8/bus/bus.h 2014-09-15 12:29:28.000000000 +0100 +++ dbus-1.8.10/bus/bus.h 2014-11-04 15:04:06.000000000 +0000 @@ -116,6 +116,7 @@ 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 -Nru --exclude aclocal.m4 --exclude configure --exclude Makefile.in dbus-1.8.8/configure.ac dbus-1.8.10/configure.ac --- dbus-1.8.8/configure.ac 2014-09-15 12:42:50.000000000 +0100 +++ dbus-1.8.10/configure.ac 2014-11-06 15:34:45.000000000 +0000 @@ -3,7 +3,7 @@ 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 @@ ## 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 -Nru --exclude aclocal.m4 --exclude configure --exclude Makefile.in dbus-1.8.8/dbus/dbus-sysdeps.h dbus-1.8.10/dbus/dbus-sysdeps.h --- dbus-1.8.8/dbus/dbus-sysdeps.h 2014-09-15 12:27:24.000000000 +0100 +++ dbus-1.8.10/dbus/dbus-sysdeps.h 2014-11-06 15:30:51.000000000 +0000 @@ -546,8 +546,6 @@ 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 @@ */ #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 -Nru --exclude aclocal.m4 --exclude configure --exclude Makefile.in dbus-1.8.8/dbus/dbus-sysdeps-util-unix.c dbus-1.8.10/dbus/dbus-sysdeps-util-unix.c --- dbus-1.8.8/dbus/dbus-sysdeps-util-unix.c 2014-09-12 12:52:11.000000000 +0100 +++ dbus-1.8.10/dbus/dbus-sysdeps-util-unix.c 2014-11-06 15:30:51.000000000 +0000 @@ -378,53 +378,140 @@ } #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; - - if (lim.rlim_cur >= limit) - 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 == 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 -Nru --exclude aclocal.m4 --exclude configure --exclude Makefile.in dbus-1.8.8/dbus/dbus-sysdeps-util-win.c dbus-1.8.10/dbus/dbus-sysdeps-util-win.c --- dbus-1.8.8/dbus/dbus-sysdeps-util-win.c 2014-09-12 12:52:11.000000000 +0100 +++ dbus-1.8.10/dbus/dbus-sysdeps-util-win.c 2014-11-06 15:30:51.000000000 +0000 @@ -258,9 +258,42 @@ 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 -Nru --exclude aclocal.m4 --exclude configure --exclude Makefile.in dbus-1.8.8/debian/changelog dbus-1.8.10/debian/changelog --- dbus-1.8.8/debian/changelog 2014-10-06 19:17:12.000000000 +0100 +++ dbus-1.8.10/debian/changelog 2014-11-06 16:28:35.000000000 +0000 @@ -1,3 +1,15 @@ +dbus (1.8.10-1) unstable; urgency=medium + + * New upstream release 1.8.10 + - raise dbus-daemon's file descriptor limit to 65536 to avoid an + opportunity for denial of service + (CVE-2014-7824, an incomplete fix for CVE-2014-3636) + * Start 'dbus-daemon --system' as root under sysvinit (it already + starts as root under systemd), so it can increase its file + descriptor limit + + -- Simon McVittie <smcv@debian.org> Thu, 06 Nov 2014 16:28:22 +0000 + dbus (1.8.8-2) unstable; urgency=medium [ Michael Biebl ] diff -Nru --exclude aclocal.m4 --exclude configure --exclude Makefile.in dbus-1.8.8/debian/dbus.init dbus-1.8.10/debian/dbus.init --- dbus-1.8.8/debian/dbus.init 2014-10-06 19:17:12.000000000 +0100 +++ dbus-1.8.10/debian/dbus.init 2014-11-06 16:28:35.000000000 +0000 @@ -69,7 +69,7 @@ log_daemon_msg "Starting $DESC" "$NAME" start-stop-daemon --start --quiet --pidfile $PIDFILE \ - --user $DAEMONUSER --exec $DAEMON -- --system $PARAMS + --exec $DAEMON -- --system $PARAMS log_end_msg $? } diff -Nru --exclude aclocal.m4 --exclude configure --exclude Makefile.in dbus-1.8.8/NEWS dbus-1.8.10/NEWS --- dbus-1.8.8/NEWS 2014-09-15 12:42:33.000000000 +0100 +++ dbus-1.8.10/NEWS 2014-11-06 15:39:02.000000000 +0000 @@ -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) ==
--- End Message ---
--- Begin Message ---
- To: Cyril Brulebois <kibi@debian.org>, 768992-done@bugs.debian.org
- Cc: Simon McVittie <smcv@debian.org>
- Subject: Re: Bug#768992: unblock: dbus/1.8.10-1
- From: Julien Cristau <jcristau@debian.org>
- Date: Wed, 12 Nov 2014 14:49:12 +0100
- Message-id: <20141112134912.GW2077@betterave.cristau.org>
- In-reply-to: <[🔎] 20141111231245.GA2640@mraw.org>
- References: <[🔎] 20141110162828.GA28555@reptile.pseudorandom.co.uk> <[🔎] 20141110164641.GP2077@betterave.cristau.org> <[🔎] 20141111231245.GA2640@mraw.org>
On Wed, Nov 12, 2014 at 00:12:45 +0100, Cyril Brulebois wrote: > Checking older build logs, I don't see any match for dbus-udeb or its > library udeb, so no objection. > added unblock-udeb. Cheers, JulienAttachment: signature.asc
Description: Digital signature
--- End Message ---