summaryrefslogtreecommitdiff
path: root/bus/bus.c
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2014-11-04 14:41:54 +0000
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2014-11-06 15:31:07 +0000
commit4e466446d27f1a3991c22307a47a81c9e93e530d (patch)
tree5e5b27972b0246ef93f9baab230cdfb042dba8e6 /bus/bus.c
parent8874d3a0c57c0cae97cbe426e3686936da53f649 (diff)
downloaddbus-4e466446d27f1a3991c22307a47a81c9e93e530d.tar.gz
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>
Diffstat (limited to 'bus/bus.c')
-rw-r--r--bus/bus.c50
1 files changed, 40 insertions, 10 deletions
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);