[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#768993: marked as done (wheezy-pu: package dbus/1.6.8-1+deb7u5)



Your message dated Mon, 24 Nov 2014 12:41:20 +0000
with message-id <20141124124120.GA30276@reptile.pseudorandom.co.uk>
and subject line Re: Bug#768993: wheezy-pu: package dbus/1.6.8-1+deb7u5
has caused the Debian Bug report #768993,
regarding wheezy-pu: package dbus/1.6.8-1+deb7u5
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.)


-- 
768993: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=768993
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
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

--- End Message ---
--- Begin Message ---
On Mon, 10 Nov 2014 at 16:31:08 +0000, Simon McVittie wrote:
> 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.

I have since discovered a regression caused by an earlier security update
(see #770551 for the corresponding testing pre-approval) which should
be fixed through the security archive, so the security team have
asked me to address CVE-2014-7824 in the same security upload.

This will get into wheezy via security rather than by me uploading to
proposed-updates, so I'm closing this bug.

    S

--- End Message ---

Reply to: