Bug#768993: wheezy-pu: package dbus/1.6.8-1+deb7u5
Package: release.debian.org
Severity: normal
Tags: wheezy
User: release.debian.org@packages.debian.org
Usertags: pu
I would like to fix denial-of-service vulnerability CVE-2014-7824 in wheezy.
The security team have indicated that they will not be issuing a DSA for this.
It's the same vulnerability for which I just requested a 1.8.10 unblock,
and basically the same patch (after fixing minor conflicts in a comment).
Source debdiff attached.
Thanks,
S
diffstat for dbus-1.6.8 dbus-1.6.8
changelog | 11
dbus.init | 2
patches/0001-CVE-2014-7824-set-fd-rlimit-to-64k-for-the-system-db.patch | 426 ++++++++++
patches/series | 2
4 files changed, 440 insertions(+), 1 deletion(-)
diff -Nru dbus-1.6.8/debian/changelog dbus-1.6.8/debian/changelog
--- dbus-1.6.8/debian/changelog 2014-09-15 19:49:38.000000000 +0100
+++ dbus-1.6.8/debian/changelog 2014-11-06 16:36:28.000000000 +0000
@@ -1,3 +1,14 @@
+dbus (1.6.8-1+deb7u5) wheezy; urgency=medium
+
+ * Fix CVE-2014-7824:
+ - Start 'dbus-daemon --system' as root under sysvinit (it already
+ starts as root under systemd), so it can increase its file
+ descriptor limit
+ - Add patch from upstream to increase dbus-daemon's file descriptor
+ limit to 65536, completing the incomplete fix for CVE-2014-3636
+
+ -- Simon McVittie <smcv@debian.org> Thu, 06 Nov 2014 16:31:34 +0000
+
dbus (1.6.8-1+deb7u4) wheezy-security; urgency=high
* Fix several security issues
diff -Nru dbus-1.6.8/debian/dbus.init dbus-1.6.8/debian/dbus.init
--- dbus-1.6.8/debian/dbus.init 2014-09-15 19:49:38.000000000 +0100
+++ dbus-1.6.8/debian/dbus.init 2014-11-06 16:36:28.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.6.8/debian/patches/0001-CVE-2014-7824-set-fd-rlimit-to-64k-for-the-system-db.patch dbus-1.6.8/debian/patches/0001-CVE-2014-7824-set-fd-rlimit-to-64k-for-the-system-db.patch
--- dbus-1.6.8/debian/patches/0001-CVE-2014-7824-set-fd-rlimit-to-64k-for-the-system-db.patch 1970-01-01 01:00:00.000000000 +0100
+++ dbus-1.6.8/debian/patches/0001-CVE-2014-7824-set-fd-rlimit-to-64k-for-the-system-db.patch 2014-11-06 16:36:28.000000000 +0000
@@ -0,0 +1,426 @@
+From 68cb9ead957314b30e604018f2dd5b0fc3b2127c Mon Sep 17 00:00:00 2001
+From: Simon McVittie <simon.mcvittie@collabora.co.uk>
+Date: Tue, 4 Nov 2014 14:41:54 +0000
+Subject: [PATCH] CVE-2014-7824: set fd rlimit to 64k for the system
+ dbus-daemon
+
+This ensures that our rlimit is actually high enough to avoid the
+denial of service described in CVE-2014-3636 part A.
+CVE-2014-7824 has been allocated for this incomplete fix.
+
+Restore the original rlimit for activated services, to avoid
+them getting undesired higher limits.
+
+(Thanks to Alban Crequy for various adjustments which have been
+included in this commit.)
+
+Bug: https://bugs.freedesktop.org/show_bug.cgi?id=85105
+Reviewed-by: Alban Crequy <alban.crequy@collabora.co.uk>
+Conflicts:
+ dbus/dbus-sysdeps-util-unix.c
+---
+ bus/activation.c | 28 +++++++-
+ bus/bus.c | 50 ++++++++++++---
+ bus/bus.h | 1 +
+ dbus/dbus-sysdeps-util-unix.c | 145 +++++++++++++++++++++++++++++++++---------
+ dbus/dbus-sysdeps-util-win.c | 35 +++++++++-
+ dbus/dbus-sysdeps.h | 11 +++-
+ 6 files changed, 227 insertions(+), 43 deletions(-)
+
+diff --git a/bus/activation.c b/bus/activation.c
+index 280cc01..b636868 100644
+--- a/bus/activation.c
++++ b/bus/activation.c
+@@ -1683,6 +1683,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,
+@@ -2114,7 +2139,8 @@ bus_activation_activate_service (BusActivation *activation,
+
+ if (!_dbus_spawn_async_with_babysitter (&pending_activation->babysitter, 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 c4eadc2..a8b153b 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;
+@@ -647,19 +648,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
+@@ -1118,6 +1138,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);
+@@ -1282,6 +1306,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 7d0b369..dac6ea5 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/dbus/dbus-sysdeps-util-unix.c b/dbus/dbus-sysdeps-util-unix.c
+index bbc3f34..4134f2a 100644
+--- a/dbus/dbus-sysdeps-util-unix.c
++++ b/dbus/dbus-sysdeps-util-unix.c
+@@ -373,53 +373,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 @limit file descriptors.
+- *
+- * If @limit is lower than the current, it will not be
+- * lowered. No error is returned if the request can
+- * not be satisfied.
+- *
+- * @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 111db9e..fe29b90 100644
+--- a/dbus/dbus-sysdeps-util-win.c
++++ b/dbus/dbus-sysdeps-util-win.c
+@@ -256,9 +256,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 64b6363..61dd52d 100644
+--- a/dbus/dbus-sysdeps.h
++++ b/dbus/dbus-sysdeps.h
+@@ -525,8 +525,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
+@@ -545,6 +543,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
+--
+2.1.3
+
diff -Nru dbus-1.6.8/debian/patches/series dbus-1.6.8/debian/patches/series
--- dbus-1.6.8/debian/patches/series 2014-09-15 19:49:38.000000000 +0100
+++ dbus-1.6.8/debian/patches/series 2014-11-06 16:36:28.000000000 +0000
@@ -13,3 +13,5 @@
0007-DBusConnection-implements-_dbus_connection_set_pendi.patch
0008-bus-enforce-pending_fd_timeout.patch
0010-_dbus_read_socket_with_unix_fds-do-not-accept-extra-.patch
+
+0001-CVE-2014-7824-set-fd-rlimit-to-64k-for-the-system-db.patch
Reply to: