mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-05-05 12:18:13 +02:00
Merge branch 'dbus-1.8'
Conflicts: NEWS configure.ac
This commit is contained in:
commit
1909a82a8a
24 changed files with 401 additions and 76 deletions
59
NEWS
59
NEWS
|
|
@ -51,6 +51,57 @@ Fixes:
|
|||
(like Mac OS X 10.6), or available in libc but unsupported by the kernel
|
||||
(fd.o #77032; rmvsxop, OBATA Akio, Patrick Welche)
|
||||
|
||||
• Fix include path for test/internal/*.c with cmake (Ralf Habacker)
|
||||
|
||||
• Change DBUS_TYPE_G_BYTE_ARRAY reference in dbus-tutorial.xml
|
||||
to the correct DBUS_TYPE_G_UCHAR_ARRAY (fd.o #80795, Thomas Haller)
|
||||
|
||||
• in dbus-monitor, do not leak file descriptors that we have monitored
|
||||
(fd.o #80603, Alban Crequy)
|
||||
|
||||
D-Bus 1.8.8 (2014-09-16)
|
||||
==
|
||||
|
||||
The "smashy smashy egg man" release.
|
||||
|
||||
Security fixes:
|
||||
|
||||
• Do not accept an extra fd in the padding of a cmsg message, which
|
||||
could lead to a 4-byte heap buffer overrun.
|
||||
(CVE-2014-3635, fd.o #83622; Simon McVittie)
|
||||
|
||||
• Reduce default for maximum Unix file descriptors passed per message
|
||||
from 1024 to 16, preventing a uid with the default maximum number of
|
||||
connections from exhausting the system bus' file descriptors under
|
||||
Linux's default rlimit. Distributors or system administrators with a
|
||||
more restrictive fd limit may wish to reduce these limits further.
|
||||
|
||||
Additionally, on Linux this prevents a second denial of service
|
||||
in which the dbus-daemon can be made to exceed the maximum number
|
||||
of fds per sendmsg() and disconnect the process that would have
|
||||
received them.
|
||||
(CVE-2014-3636, fd.o #82820; Alban Crequy)
|
||||
|
||||
• Disconnect connections that still have a fd pending unmarshalling after
|
||||
a new configurable limit, pending_fd_timeout (defaulting to 150 seconds),
|
||||
removing the possibility of creating an abusive connection that cannot be
|
||||
disconnected by setting up a circular reference to a connection's
|
||||
file descriptor.
|
||||
(CVE-2014-3637, fd.o #80559; Alban Crequy)
|
||||
|
||||
• Reduce default for maximum pending replies per connection from 8192 to 128,
|
||||
mitigating an algorithmic complexity denial-of-service attack
|
||||
(CVE-2014-3638, fd.o #81053; Alban Crequy)
|
||||
|
||||
• Reduce default for authentication timeout on the system bus from
|
||||
30 seconds to 5 seconds, avoiding denial of service by using up
|
||||
all unauthenticated connection slots; and when all unauthenticated
|
||||
connection slots are used up, make new connection attempts block
|
||||
instead of disconnecting them.
|
||||
(CVE-2014-3639, fd.o #80919; Alban Crequy)
|
||||
|
||||
Other fixes:
|
||||
|
||||
• Check for libsystemd from systemd >= 209, falling back to
|
||||
the older separate libraries if not found (Umut Tezduyar Lindskog,
|
||||
Simon McVittie)
|
||||
|
|
@ -62,17 +113,9 @@ Fixes:
|
|||
• Fix compilation with --enable-stats (fd.o #81043, Gentoo #507232;
|
||||
Alban Crequy)
|
||||
|
||||
• Fix include path for test/internal/*.c with cmake (Ralf Habacker)
|
||||
|
||||
• Change DBUS_TYPE_G_BYTE_ARRAY reference in dbus-tutorial.xml
|
||||
to the correct DBUS_TYPE_G_UCHAR_ARRAY (fd.o #80795, Thomas Haller)
|
||||
|
||||
• Improve documentation for running tests on Windows (fd.o #41252,
|
||||
Ralf Habacker)
|
||||
|
||||
• in dbus-monitor, do not leak file descriptors that we have monitored
|
||||
(fd.o #80603, Alban Crequy)
|
||||
|
||||
D-Bus 1.8.6 (2014-06-02)
|
||||
==
|
||||
|
||||
|
|
|
|||
43
bus/bus.c
43
bus/bus.c
|
|
@ -39,6 +39,7 @@
|
|||
#include <dbus/dbus-hash.h>
|
||||
#include <dbus/dbus-credentials.h>
|
||||
#include <dbus/dbus-internals.h>
|
||||
#include <dbus/dbus-server-protected.h>
|
||||
|
||||
#ifdef DBUS_CYGWIN
|
||||
#include <signal.h>
|
||||
|
|
@ -68,6 +69,7 @@ struct BusContext
|
|||
unsigned int keep_umask : 1;
|
||||
unsigned int allow_anonymous : 1;
|
||||
unsigned int systemd_activation : 1;
|
||||
dbus_bool_t watches_enabled;
|
||||
};
|
||||
|
||||
static dbus_int32_t server_data_slot = -1;
|
||||
|
|
@ -758,6 +760,8 @@ bus_context_new (const DBusString *config_file,
|
|||
goto failed;
|
||||
}
|
||||
|
||||
context->watches_enabled = TRUE;
|
||||
|
||||
context->registry = bus_registry_new (context);
|
||||
if (context->registry == NULL)
|
||||
{
|
||||
|
|
@ -1236,6 +1240,12 @@ bus_context_get_auth_timeout (BusContext *context)
|
|||
return context->limits.auth_timeout;
|
||||
}
|
||||
|
||||
int
|
||||
bus_context_get_pending_fd_timeout (BusContext *context)
|
||||
{
|
||||
return context->limits.pending_fd_timeout;
|
||||
}
|
||||
|
||||
int
|
||||
bus_context_get_max_completed_connections (BusContext *context)
|
||||
{
|
||||
|
|
@ -1658,3 +1668,36 @@ bus_context_check_security_policy (BusContext *context,
|
|||
_dbus_verbose ("security policy allowing message\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
bus_context_check_all_watches (BusContext *context)
|
||||
{
|
||||
DBusList *link;
|
||||
dbus_bool_t enabled = TRUE;
|
||||
|
||||
if (bus_connections_get_n_incomplete (context->connections) >=
|
||||
bus_context_get_max_incomplete_connections (context))
|
||||
{
|
||||
enabled = FALSE;
|
||||
}
|
||||
|
||||
if (context->watches_enabled == enabled)
|
||||
return;
|
||||
|
||||
context->watches_enabled = enabled;
|
||||
|
||||
for (link = _dbus_list_get_first_link (&context->servers);
|
||||
link != NULL;
|
||||
link = _dbus_list_get_next_link (&context->servers, link))
|
||||
{
|
||||
/* A BusContext might contains several DBusServer (if there are
|
||||
* several <listen> configuration items) and a DBusServer might
|
||||
* contain several DBusWatch in its DBusWatchList (if getaddrinfo
|
||||
* returns several addresses on a dual IPv4-IPv6 stack or if
|
||||
* systemd passes several fds).
|
||||
* We want to enable/disable them all.
|
||||
*/
|
||||
DBusServer *server = link->data;
|
||||
_dbus_server_toggle_all_watches (server, enabled);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ typedef struct
|
|||
long max_message_unix_fds; /**< Max number of unix fds of a single message*/
|
||||
int activation_timeout; /**< How long to wait for an activation to time out */
|
||||
int auth_timeout; /**< How long to wait for an authentication to time out */
|
||||
int pending_fd_timeout; /**< How long to wait for a D-Bus message with a fd to time out */
|
||||
int max_completed_connections; /**< Max number of authorized connections */
|
||||
int max_incomplete_connections; /**< Max number of incomplete connections */
|
||||
int max_connections_per_user; /**< Max number of connections auth'd as same user */
|
||||
|
|
@ -106,6 +107,7 @@ BusClientPolicy* bus_context_create_client_policy (BusContext
|
|||
DBusError *error);
|
||||
int bus_context_get_activation_timeout (BusContext *context);
|
||||
int bus_context_get_auth_timeout (BusContext *context);
|
||||
int bus_context_get_pending_fd_timeout (BusContext *context);
|
||||
int bus_context_get_max_completed_connections (BusContext *context);
|
||||
int bus_context_get_max_incomplete_connections (BusContext *context);
|
||||
int bus_context_get_max_connections_per_user (BusContext *context);
|
||||
|
|
@ -125,5 +127,6 @@ dbus_bool_t bus_context_check_security_policy (BusContext
|
|||
DBusConnection *proposed_recipient,
|
||||
DBusMessage *message,
|
||||
DBusError *error);
|
||||
void bus_context_check_all_watches (BusContext *context);
|
||||
|
||||
#endif /* BUS_BUS_H */
|
||||
|
|
|
|||
|
|
@ -438,7 +438,12 @@ bus_config_parser_new (const DBusString *basedir,
|
|||
* and legitimate auth will fail. If interactive auth (ask user for
|
||||
* password) is allowed, then potentially it has to be quite long.
|
||||
*/
|
||||
parser->limits.auth_timeout = 30000; /* 30 seconds */
|
||||
parser->limits.auth_timeout = 5000; /* 5 seconds */
|
||||
|
||||
/* Do not allow a fd to stay forever in dbus-daemon
|
||||
* https://bugs.freedesktop.org/show_bug.cgi?id=80559
|
||||
*/
|
||||
parser->limits.pending_fd_timeout = 150000; /* 2.5 minutes */
|
||||
|
||||
parser->limits.max_incomplete_connections = 64;
|
||||
parser->limits.max_connections_per_user = 256;
|
||||
|
|
@ -467,7 +472,7 @@ bus_config_parser_new (const DBusString *basedir,
|
|||
/* this is effectively a limit on message queue size for messages
|
||||
* that require a reply
|
||||
*/
|
||||
parser->limits.max_replies_per_connection = 1024*8;
|
||||
parser->limits.max_replies_per_connection = 128;
|
||||
}
|
||||
|
||||
parser->refcount = 1;
|
||||
|
|
@ -1902,6 +1907,12 @@ set_limit (BusConfigParser *parser,
|
|||
must_be_int = TRUE;
|
||||
parser->limits.auth_timeout = value;
|
||||
}
|
||||
else if (strcmp (name, "pending_fd_timeout") == 0)
|
||||
{
|
||||
must_be_positive = TRUE;
|
||||
must_be_int = TRUE;
|
||||
parser->limits.pending_fd_timeout = value;
|
||||
}
|
||||
else if (strcmp (name, "reply_timeout") == 0)
|
||||
{
|
||||
must_be_positive = TRUE;
|
||||
|
|
@ -3108,6 +3119,7 @@ limits_equal (const BusLimits *a,
|
|||
|| a->max_message_unix_fds == b->max_message_unix_fds
|
||||
|| a->activation_timeout == b->activation_timeout
|
||||
|| a->auth_timeout == b->auth_timeout
|
||||
|| a->pending_fd_timeout == b->pending_fd_timeout
|
||||
|| a->max_completed_connections == b->max_completed_connections
|
||||
|| a->max_incomplete_connections == b->max_incomplete_connections
|
||||
|| a->max_connections_per_user == b->max_connections_per_user
|
||||
|
|
|
|||
113
bus/connection.c
113
bus/connection.c
|
|
@ -33,6 +33,7 @@
|
|||
#include <dbus/dbus-list.h>
|
||||
#include <dbus/dbus-hash.h>
|
||||
#include <dbus/dbus-timeout.h>
|
||||
#include <dbus/dbus-connection-internal.h>
|
||||
|
||||
/* Trim executed commands to this length; we want to keep logs readable */
|
||||
#define MAX_LOG_COMMAND_LEN 50
|
||||
|
|
@ -102,6 +103,8 @@ typedef struct
|
|||
int peak_match_rules;
|
||||
int peak_bus_names;
|
||||
#endif
|
||||
int n_pending_unix_fds;
|
||||
DBusTimeout *pending_unix_fds_timeout;
|
||||
} BusConnectionData;
|
||||
|
||||
static dbus_bool_t bus_pending_reply_expired (BusExpireList *list,
|
||||
|
|
@ -268,6 +271,15 @@ bus_connection_disconnected (DBusConnection *connection)
|
|||
|
||||
dbus_connection_set_dispatch_status_function (connection,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
if (d->pending_unix_fds_timeout)
|
||||
{
|
||||
_dbus_loop_remove_timeout (bus_context_get_loop (d->connections->context),
|
||||
d->pending_unix_fds_timeout);
|
||||
_dbus_timeout_unref (d->pending_unix_fds_timeout);
|
||||
}
|
||||
d->pending_unix_fds_timeout = NULL;
|
||||
_dbus_connection_set_pending_fds_function (connection, NULL, NULL);
|
||||
|
||||
bus_connection_remove_transactions (connection);
|
||||
|
||||
|
|
@ -293,6 +305,10 @@ bus_connection_disconnected (DBusConnection *connection)
|
|||
_dbus_list_remove_link (&d->connections->incomplete, d->link_in_connection_list);
|
||||
d->link_in_connection_list = NULL;
|
||||
d->connections->n_incomplete -= 1;
|
||||
|
||||
/* If we have dropped below the max. number of incomplete
|
||||
* connections, start accept()ing again */
|
||||
bus_context_check_all_watches (d->connections->context);
|
||||
}
|
||||
|
||||
_dbus_assert (d->connections->n_incomplete >= 0);
|
||||
|
|
@ -588,6 +604,42 @@ oom:
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
check_pending_fds_cb (DBusConnection *connection)
|
||||
{
|
||||
BusConnectionData *d = BUS_CONNECTION_DATA (connection);
|
||||
int n_pending_unix_fds_old = d->n_pending_unix_fds;
|
||||
int n_pending_unix_fds_new;
|
||||
|
||||
n_pending_unix_fds_new = _dbus_connection_get_pending_fds_count (connection);
|
||||
|
||||
_dbus_verbose ("Pending fds count changed on connection %p: %d -> %d\n",
|
||||
connection, n_pending_unix_fds_old, n_pending_unix_fds_new);
|
||||
|
||||
if (n_pending_unix_fds_old == 0 && n_pending_unix_fds_new > 0)
|
||||
{
|
||||
_dbus_timeout_set_interval (d->pending_unix_fds_timeout,
|
||||
bus_context_get_pending_fd_timeout (d->connections->context));
|
||||
_dbus_timeout_set_enabled (d->pending_unix_fds_timeout, TRUE);
|
||||
}
|
||||
|
||||
if (n_pending_unix_fds_old > 0 && n_pending_unix_fds_new == 0)
|
||||
{
|
||||
_dbus_timeout_set_enabled (d->pending_unix_fds_timeout, FALSE);
|
||||
}
|
||||
|
||||
|
||||
d->n_pending_unix_fds = n_pending_unix_fds_new;
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
pending_unix_fds_timeout_cb (void *data)
|
||||
{
|
||||
DBusConnection *connection = data;
|
||||
dbus_connection_close (connection);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
dbus_bool_t
|
||||
bus_connections_setup_connection (BusConnections *connections,
|
||||
DBusConnection *connection)
|
||||
|
|
@ -683,36 +735,38 @@ bus_connections_setup_connection (BusConnections *connections,
|
|||
}
|
||||
}
|
||||
|
||||
/* Setup pending fds timeout (see #80559) */
|
||||
d->pending_unix_fds_timeout = _dbus_timeout_new (100, /* irrelevant */
|
||||
pending_unix_fds_timeout_cb,
|
||||
connection, NULL);
|
||||
if (d->pending_unix_fds_timeout == NULL)
|
||||
goto out;
|
||||
|
||||
_dbus_timeout_set_enabled (d->pending_unix_fds_timeout, FALSE);
|
||||
if (!_dbus_loop_add_timeout (bus_context_get_loop (connections->context),
|
||||
d->pending_unix_fds_timeout))
|
||||
goto out;
|
||||
|
||||
_dbus_connection_set_pending_fds_function (connection,
|
||||
(DBusPendingFdsChangeFunction) check_pending_fds_cb,
|
||||
connection);
|
||||
|
||||
_dbus_list_append_link (&connections->incomplete, d->link_in_connection_list);
|
||||
connections->n_incomplete += 1;
|
||||
|
||||
dbus_connection_ref (connection);
|
||||
|
||||
/* Note that we might disconnect ourselves here, but it only takes
|
||||
* effect on return to the main loop. We call this to free up
|
||||
* expired connections if possible, and to queue the timeout for our
|
||||
* own expiration.
|
||||
*/
|
||||
bus_connections_expire_incomplete (connections);
|
||||
|
||||
/* And we might also disconnect ourselves here, but again it
|
||||
* only takes effect on return to main loop.
|
||||
*/
|
||||
if (connections->n_incomplete >
|
||||
bus_context_get_max_incomplete_connections (connections->context))
|
||||
{
|
||||
_dbus_verbose ("Number of incomplete connections exceeds max, dropping oldest one\n");
|
||||
|
||||
_dbus_assert (connections->incomplete != NULL);
|
||||
/* Disconnect the oldest unauthenticated connection. FIXME
|
||||
* would it be more secure to drop a *random* connection? This
|
||||
* algorithm seems to mean that if someone can create new
|
||||
* connections quickly enough, they can keep anyone else from
|
||||
* completing authentication. But random may or may not really
|
||||
* help with that, a more elaborate solution might be required.
|
||||
*/
|
||||
dbus_connection_close (connections->incomplete->data);
|
||||
}
|
||||
/* The listening socket is removed from the main loop,
|
||||
* i.e. does not accept(), while n_incomplete is at its
|
||||
* maximum value; so we shouldn't get here in that case */
|
||||
_dbus_assert (connections->n_incomplete <=
|
||||
bus_context_get_max_incomplete_connections (connections->context));
|
||||
|
||||
/* If we have the maximum number of incomplete connections,
|
||||
* stop accept()ing any more, to avert a DoS. See fd.o #80919 */
|
||||
bus_context_check_all_watches (d->connections->context);
|
||||
|
||||
retval = TRUE;
|
||||
|
||||
|
|
@ -744,6 +798,13 @@ bus_connections_setup_connection (BusConnections *connections,
|
|||
dbus_connection_set_dispatch_status_function (connection,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
if (d->pending_unix_fds_timeout)
|
||||
_dbus_timeout_unref (d->pending_unix_fds_timeout);
|
||||
|
||||
d->pending_unix_fds_timeout = NULL;
|
||||
|
||||
_dbus_connection_set_pending_fds_function (connection, NULL, NULL);
|
||||
|
||||
if (d->link_in_connection_list != NULL)
|
||||
{
|
||||
_dbus_assert (d->link_in_connection_list->next == NULL);
|
||||
|
|
@ -1419,6 +1480,10 @@ bus_connection_complete (DBusConnection *connection,
|
|||
_dbus_assert (d->connections->n_incomplete >= 0);
|
||||
_dbus_assert (d->connections->n_completed > 0);
|
||||
|
||||
/* If we have dropped below the max. number of incomplete
|
||||
* connections, start accept()ing again */
|
||||
bus_context_check_all_watches (d->connections->context);
|
||||
|
||||
/* See if we can remove the timeout */
|
||||
bus_connections_expire_incomplete (d->connections);
|
||||
|
||||
|
|
@ -2348,7 +2413,6 @@ bus_transaction_add_cancel_hook (BusTransaction *transaction,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef DBUS_ENABLE_STATS
|
||||
int
|
||||
bus_connections_get_n_active (BusConnections *connections)
|
||||
{
|
||||
|
|
@ -2361,6 +2425,7 @@ bus_connections_get_n_incomplete (BusConnections *connections)
|
|||
return connections->n_incomplete;
|
||||
}
|
||||
|
||||
#ifdef DBUS_ENABLE_STATS
|
||||
int
|
||||
bus_connections_get_total_match_rules (BusConnections *connections)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -139,9 +139,10 @@ dbus_bool_t bus_transaction_add_cancel_hook (BusTransaction *
|
|||
void *data,
|
||||
DBusFreeFunction free_data_function);
|
||||
|
||||
/* called by stats.c, only present if DBUS_ENABLE_STATS */
|
||||
int bus_connections_get_n_active (BusConnections *connections);
|
||||
int bus_connections_get_n_incomplete (BusConnections *connections);
|
||||
|
||||
/* called by stats.c, only present if DBUS_ENABLE_STATS */
|
||||
int bus_connections_get_total_match_rules (BusConnections *connections);
|
||||
int bus_connections_get_peak_match_rules (BusConnections *connections);
|
||||
int bus_connections_get_peak_match_rules_per_conn (BusConnections *connections);
|
||||
|
|
|
|||
|
|
@ -49,9 +49,11 @@
|
|||
<limit name="max_outgoing_bytes">1000000000</limit>
|
||||
<limit name="max_outgoing_unix_fds">250000000</limit>
|
||||
<limit name="max_message_size">1000000000</limit>
|
||||
<limit name="max_message_unix_fds">@DEFAULT_MESSAGE_UNIX_FDS@</limit>
|
||||
<!-- We do not override max_message_unix_fds here since the in-kernel
|
||||
limit is also relatively low -->
|
||||
<limit name="service_start_timeout">120000</limit>
|
||||
<limit name="auth_timeout">240000</limit>
|
||||
<limit name="pending_fd_timeout">150000</limit>
|
||||
<limit name="max_completed_connections">100000</limit>
|
||||
<limit name="max_incomplete_connections">10000</limit>
|
||||
<limit name="max_connections_per_user">100000</limit>
|
||||
|
|
|
|||
|
|
@ -411,10 +411,6 @@ endif (WIN32)
|
|||
|
||||
set (DBUS_USER )
|
||||
|
||||
# In Autotools this has a different default on QNX, but there seems little
|
||||
# point in replicating that here; if you're on an unusual Unix, use Autotools.
|
||||
set (DEFAULT_MESSAGE_UNIX_FDS 1024)
|
||||
|
||||
# This won't work on Windows. It's not meant to - the system bus is
|
||||
# meaningless on Windows anyway.
|
||||
#
|
||||
|
|
|
|||
|
|
@ -82,8 +82,6 @@
|
|||
# define DBUS_ENABLE_X11_AUTOLAUNCH 1
|
||||
#endif
|
||||
|
||||
#define DBUS_DEFAULT_MESSAGE_UNIX_FDS @DEFAULT_MESSAGE_UNIX_FDS@
|
||||
|
||||
#define _DBUS_VA_COPY_ASSIGN(a1,a2) { a1 = a2; }
|
||||
|
||||
#cmakedefine DBUS_VA_COPY_FUNC
|
||||
|
|
|
|||
13
configure.ac
13
configure.ac
|
|
@ -37,7 +37,7 @@ LT_CURRENT=11
|
|||
|
||||
## increment any time the source changes; set to
|
||||
## 0 if you increment CURRENT
|
||||
LT_REVISION=6
|
||||
LT_REVISION=7
|
||||
|
||||
## increment if any interfaces have been added; set to 0
|
||||
## if any interfaces have been changed or removed. removal has
|
||||
|
|
@ -1245,17 +1245,6 @@ if test x$with_valgrind != xno; then
|
|||
AC_DEFINE([WITH_VALGRIND], [1], [Define to add Valgrind instrumentation])
|
||||
fi
|
||||
|
||||
# Determine maximum number of Unix fds which may be passed
|
||||
AS_CASE([$host_os],
|
||||
[*qnx*],
|
||||
[DEFAULT_MESSAGE_UNIX_FDS=256],
|
||||
[*],
|
||||
[DEFAULT_MESSAGE_UNIX_FDS=1024])
|
||||
AC_DEFINE_UNQUOTED([DBUS_DEFAULT_MESSAGE_UNIX_FDS],
|
||||
[$DEFAULT_MESSAGE_UNIX_FDS],
|
||||
[Default for dbus_connection_get_max_message_unix_fds()])
|
||||
AC_SUBST([DEFAULT_MESSAGE_UNIX_FDS])
|
||||
|
||||
#### Set up final flags
|
||||
LIBDBUS_LIBS="$THREAD_LIBS $NETWORK_libs $SYSTEMD_LIBS"
|
||||
AC_SUBST([LIBDBUS_LIBS])
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@ typedef enum
|
|||
/** default timeout value when waiting for a message reply, 25 seconds */
|
||||
#define _DBUS_DEFAULT_TIMEOUT_VALUE (25 * 1000)
|
||||
|
||||
typedef void (* DBusPendingFdsChangeFunction) (void *data);
|
||||
|
||||
void _dbus_connection_lock (DBusConnection *connection);
|
||||
void _dbus_connection_unlock (DBusConnection *connection);
|
||||
DBusConnection * _dbus_connection_ref_unlocked (DBusConnection *connection);
|
||||
|
|
@ -100,6 +102,10 @@ void _dbus_connection_test_get_locks (DBusConnectio
|
|||
DBusMutex **io_path_mutex_loc,
|
||||
DBusCondVar **dispatch_cond_loc,
|
||||
DBusCondVar **io_path_cond_loc);
|
||||
int _dbus_connection_get_pending_fds_count (DBusConnection *connection);
|
||||
void _dbus_connection_set_pending_fds_function (DBusConnection *connection,
|
||||
DBusPendingFdsChangeFunction callback,
|
||||
void *data);
|
||||
|
||||
/* if DBUS_ENABLE_STATS */
|
||||
void _dbus_connection_get_stats (DBusConnection *connection,
|
||||
|
|
|
|||
|
|
@ -2549,6 +2549,33 @@ _dbus_connection_block_pending_call (DBusPendingCall *pending)
|
|||
dbus_pending_call_unref (pending);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return how many file descriptors are pending in the loader
|
||||
*
|
||||
* @param connection the connection
|
||||
*/
|
||||
int
|
||||
_dbus_connection_get_pending_fds_count (DBusConnection *connection)
|
||||
{
|
||||
return _dbus_transport_get_pending_fds_count (connection->transport);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a function to be called whenever the number of pending file
|
||||
* descriptors in the loader change.
|
||||
*
|
||||
* @param connection the connection
|
||||
* @param callback the callback
|
||||
*/
|
||||
void
|
||||
_dbus_connection_set_pending_fds_function (DBusConnection *connection,
|
||||
DBusPendingFdsChangeFunction callback,
|
||||
void *data)
|
||||
{
|
||||
_dbus_transport_set_pending_fds_function (connection->transport,
|
||||
callback, data);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -96,6 +96,10 @@ long _dbus_message_loader_get_max_message_size (DBusMessageLoader
|
|||
void _dbus_message_loader_set_max_message_unix_fds(DBusMessageLoader *loader,
|
||||
long n);
|
||||
long _dbus_message_loader_get_max_message_unix_fds(DBusMessageLoader *loader);
|
||||
int _dbus_message_loader_get_pending_fds_count (DBusMessageLoader *loader);
|
||||
void _dbus_message_loader_set_pending_fds_function (DBusMessageLoader *loader,
|
||||
void (* callback) (void *),
|
||||
void *data);
|
||||
|
||||
typedef struct DBusInitialFDs DBusInitialFDs;
|
||||
DBusInitialFDs *_dbus_check_fdleaks_enter (void);
|
||||
|
|
|
|||
|
|
@ -80,6 +80,8 @@ struct DBusMessageLoader
|
|||
int *unix_fds; /**< File descriptors that have been read from the transport but not yet been handed to any message. Array will be allocated at first use. */
|
||||
unsigned n_unix_fds_allocated; /**< Number of file descriptors this array has space for */
|
||||
unsigned n_unix_fds; /**< Number of valid file descriptors in array */
|
||||
void (* unix_fds_change) (void *); /**< Notify when the pending fds change */
|
||||
void *unix_fds_change_data;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "dbus-list.h"
|
||||
#include "dbus-threads-internal.h"
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
#include "dbus-sysdeps.h"
|
||||
#include "dbus-sysdeps-unix.h"
|
||||
#endif
|
||||
|
||||
|
|
@ -4058,6 +4059,9 @@ _dbus_message_loader_return_unix_fds(DBusMessageLoader *loader,
|
|||
|
||||
loader->n_unix_fds += n_fds;
|
||||
loader->unix_fds_outstanding = FALSE;
|
||||
|
||||
if (n_fds && loader->unix_fds_change)
|
||||
loader->unix_fds_change (loader->unix_fds_change_data);
|
||||
#else
|
||||
_dbus_assert_not_reached("Platform doesn't support unix fd passing");
|
||||
#endif
|
||||
|
|
@ -4205,6 +4209,9 @@ load_message (DBusMessageLoader *loader,
|
|||
message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds;
|
||||
loader->n_unix_fds -= n_unix_fds;
|
||||
memmove (loader->unix_fds, loader->unix_fds + n_unix_fds, loader->n_unix_fds * sizeof (loader->unix_fds[0]));
|
||||
|
||||
if (loader->unix_fds_change)
|
||||
loader->unix_fds_change (loader->unix_fds_change_data);
|
||||
}
|
||||
else
|
||||
message->unix_fds = NULL;
|
||||
|
|
@ -4498,6 +4505,40 @@ _dbus_message_loader_get_max_message_unix_fds (DBusMessageLoader *loader)
|
|||
return loader->max_message_unix_fds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return how many file descriptors are pending in the loader
|
||||
*
|
||||
* @param loader the loader
|
||||
*/
|
||||
int
|
||||
_dbus_message_loader_get_pending_fds_count (DBusMessageLoader *loader)
|
||||
{
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
return loader->n_unix_fds;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a function to be called whenever the number of pending file
|
||||
* descriptors in the loader change.
|
||||
*
|
||||
* @param loader the loader
|
||||
* @param callback the callback
|
||||
* @param data the data for the callback
|
||||
*/
|
||||
void
|
||||
_dbus_message_loader_set_pending_fds_function (DBusMessageLoader *loader,
|
||||
void (* callback) (void *),
|
||||
void *data)
|
||||
{
|
||||
#ifdef HAVE_UNIX_FD_PASSING
|
||||
loader->unix_fds_change = callback;
|
||||
loader->unix_fds_change_data = data;
|
||||
#endif
|
||||
}
|
||||
|
||||
static DBusDataSlotAllocator slot_allocator =
|
||||
_DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (message_slots));
|
||||
|
||||
|
|
|
|||
|
|
@ -99,9 +99,8 @@ dbus_bool_t _dbus_server_add_watch (DBusServer *server,
|
|||
DBusWatch *watch);
|
||||
void _dbus_server_remove_watch (DBusServer *server,
|
||||
DBusWatch *watch);
|
||||
void _dbus_server_toggle_watch (DBusServer *server,
|
||||
DBusWatch *watch,
|
||||
dbus_bool_t enabled);
|
||||
void _dbus_server_toggle_all_watches (DBusServer *server,
|
||||
dbus_bool_t enabled);
|
||||
dbus_bool_t _dbus_server_add_timeout (DBusServer *server,
|
||||
DBusTimeout *timeout);
|
||||
void _dbus_server_remove_timeout (DBusServer *server,
|
||||
|
|
|
|||
|
|
@ -312,26 +312,17 @@ _dbus_server_remove_watch (DBusServer *server,
|
|||
}
|
||||
|
||||
/**
|
||||
* Toggles a watch and notifies app via server's
|
||||
* DBusWatchToggledFunction if available. It's an error to call this
|
||||
* function on a watch that was not previously added.
|
||||
* Toggles all watch and notifies app via server's
|
||||
* DBusWatchToggledFunction if available.
|
||||
*
|
||||
* @param server the server.
|
||||
* @param watch the watch to toggle.
|
||||
* @param enabled whether to enable or disable
|
||||
*/
|
||||
void
|
||||
_dbus_server_toggle_watch (DBusServer *server,
|
||||
DBusWatch *watch,
|
||||
dbus_bool_t enabled)
|
||||
_dbus_server_toggle_all_watches (DBusServer *server,
|
||||
dbus_bool_t enabled)
|
||||
{
|
||||
_dbus_assert (watch != NULL);
|
||||
|
||||
HAVE_LOCK_CHECK (server);
|
||||
protected_change_watch (server, watch,
|
||||
NULL, NULL,
|
||||
_dbus_watch_list_toggle_watch,
|
||||
enabled);
|
||||
_dbus_watch_list_toggle_all_watches (server->watches, enabled);
|
||||
}
|
||||
|
||||
/** Function to be called in protected_change_timeout() with refcount held */
|
||||
|
|
|
|||
|
|
@ -323,6 +323,12 @@ _dbus_read_socket_with_unix_fds (int fd,
|
|||
m.msg_control = alloca(m.msg_controllen);
|
||||
memset(m.msg_control, 0, m.msg_controllen);
|
||||
|
||||
/* Do not include the padding at the end when we tell the kernel
|
||||
* how much we're willing to receive. This avoids getting
|
||||
* the padding filled with additional fds that we weren't expecting,
|
||||
* if a (potentially malicious) sender included them. (fd.o #83622) */
|
||||
m.msg_controllen = CMSG_LEN (*n_fds * sizeof(int));
|
||||
|
||||
again:
|
||||
|
||||
bytes_read = recvmsg(fd, &m, 0
|
||||
|
|
@ -362,18 +368,49 @@ _dbus_read_socket_with_unix_fds (int fd,
|
|||
for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm))
|
||||
if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS)
|
||||
{
|
||||
unsigned i;
|
||||
size_t i;
|
||||
int *payload = (int *) CMSG_DATA (cm);
|
||||
size_t payload_len_bytes = (cm->cmsg_len - CMSG_LEN (0));
|
||||
size_t payload_len_fds = payload_len_bytes / sizeof (int);
|
||||
size_t fds_to_use;
|
||||
|
||||
_dbus_assert(cm->cmsg_len <= CMSG_LEN(*n_fds * sizeof(int)));
|
||||
*n_fds = (cm->cmsg_len - CMSG_LEN(0)) / sizeof(int);
|
||||
/* Every non-negative int fits in a size_t without truncation,
|
||||
* and we already know that *n_fds is non-negative, so
|
||||
* casting (size_t) *n_fds is OK */
|
||||
_DBUS_STATIC_ASSERT (sizeof (size_t) >= sizeof (int));
|
||||
|
||||
memcpy(fds, CMSG_DATA(cm), *n_fds * sizeof(int));
|
||||
if (_DBUS_LIKELY (payload_len_fds <= (size_t) *n_fds))
|
||||
{
|
||||
/* The fds in the payload will fit in our buffer */
|
||||
fds_to_use = payload_len_fds;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Too many fds in the payload. This shouldn't happen
|
||||
* any more because we're setting m.msg_controllen to
|
||||
* the exact number we can accept, but be safe and
|
||||
* truncate. */
|
||||
fds_to_use = (size_t) *n_fds;
|
||||
|
||||
/* Close the excess fds to avoid DoS: if they stayed open,
|
||||
* someone could send us an extra fd per message
|
||||
* and we'd eventually run out. */
|
||||
for (i = fds_to_use; i < payload_len_fds; i++)
|
||||
{
|
||||
close (payload[i]);
|
||||
}
|
||||
}
|
||||
|
||||
memcpy (fds, payload, fds_to_use * sizeof (int));
|
||||
found = TRUE;
|
||||
/* This cannot overflow because we have chosen fds_to_use
|
||||
* to be <= *n_fds */
|
||||
*n_fds = (int) fds_to_use;
|
||||
|
||||
/* Linux doesn't tell us whether MSG_CMSG_CLOEXEC actually
|
||||
worked, hence we need to go through this list and set
|
||||
CLOEXEC everywhere in any case */
|
||||
for (i = 0; i < *n_fds; i++)
|
||||
for (i = 0; i < fds_to_use; i++)
|
||||
_dbus_fd_set_close_on_exec(fds[i]);
|
||||
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -556,6 +556,14 @@ void _dbus_request_file_descriptor_limit (unsigned int limit);
|
|||
const char *
|
||||
_dbus_replace_install_prefix (const char *configure_time_path);
|
||||
|
||||
/* Do not set this too high: it is a denial-of-service risk.
|
||||
* See <https://bugs.freedesktop.org/show_bug.cgi?id=82820>
|
||||
*
|
||||
* (This needs to be in the non-Unix-specific header so that
|
||||
* the config-parser can use it.)
|
||||
*/
|
||||
#define DBUS_DEFAULT_MESSAGE_UNIX_FDS 16
|
||||
|
||||
/** @} */
|
||||
|
||||
DBUS_END_DECLS
|
||||
|
|
|
|||
|
|
@ -1512,6 +1512,33 @@ _dbus_transport_set_allow_anonymous (DBusTransport *transport,
|
|||
transport->allow_anonymous = value != FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return how many file descriptors are pending in the loader
|
||||
*
|
||||
* @param transport the transport
|
||||
*/
|
||||
int
|
||||
_dbus_transport_get_pending_fds_count (DBusTransport *transport)
|
||||
{
|
||||
return _dbus_message_loader_get_pending_fds_count (transport->loader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a function to be called whenever the number of pending file
|
||||
* descriptors in the loader change.
|
||||
*
|
||||
* @param transport the transport
|
||||
* @param callback the callback
|
||||
*/
|
||||
void
|
||||
_dbus_transport_set_pending_fds_function (DBusTransport *transport,
|
||||
void (* callback) (void *),
|
||||
void *data)
|
||||
{
|
||||
_dbus_message_loader_set_pending_fds_function (transport->loader,
|
||||
callback, data);
|
||||
}
|
||||
|
||||
#ifdef DBUS_ENABLE_STATS
|
||||
void
|
||||
_dbus_transport_get_stats (DBusTransport *transport,
|
||||
|
|
|
|||
|
|
@ -97,6 +97,10 @@ dbus_bool_t _dbus_transport_set_auth_mechanisms (DBusTransport
|
|||
const char **mechanisms);
|
||||
void _dbus_transport_set_allow_anonymous (DBusTransport *transport,
|
||||
dbus_bool_t value);
|
||||
int _dbus_transport_get_pending_fds_count (DBusTransport *transport);
|
||||
void _dbus_transport_set_pending_fds_function (DBusTransport *transport,
|
||||
void (* callback) (void *),
|
||||
void *data);
|
||||
|
||||
/* if DBUS_ENABLE_STATS */
|
||||
void _dbus_transport_get_stats (DBusTransport *transport,
|
||||
|
|
|
|||
|
|
@ -454,6 +454,27 @@ _dbus_watch_list_toggle_watch (DBusWatchList *watch_list,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets all watches to the given enabled state, invoking the
|
||||
* application's DBusWatchToggledFunction if appropriate.
|
||||
*
|
||||
* @param watch_list the watch list.
|
||||
* @param enabled #TRUE to enable
|
||||
*/
|
||||
void
|
||||
_dbus_watch_list_toggle_all_watches (DBusWatchList *watch_list,
|
||||
dbus_bool_t enabled)
|
||||
{
|
||||
DBusList *link;
|
||||
|
||||
for (link = _dbus_list_get_first_link (&watch_list->watches);
|
||||
link != NULL;
|
||||
link = _dbus_list_get_next_link (&watch_list->watches, link))
|
||||
{
|
||||
_dbus_watch_list_toggle_watch (watch_list, link->data, enabled);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the handler for the watch.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -76,6 +76,8 @@ void _dbus_watch_list_remove_watch (DBusWatchList *watch_li
|
|||
void _dbus_watch_list_toggle_watch (DBusWatchList *watch_list,
|
||||
DBusWatch *watch,
|
||||
dbus_bool_t enabled);
|
||||
void _dbus_watch_list_toggle_all_watches (DBusWatchList *watch_list,
|
||||
dbus_bool_t enabled);
|
||||
dbus_bool_t _dbus_watch_get_enabled (DBusWatch *watch);
|
||||
|
||||
dbus_bool_t _dbus_watch_get_oom_last_time (DBusWatch *watch);
|
||||
|
|
|
|||
|
|
@ -528,6 +528,10 @@ Available limit names are:</para>
|
|||
"auth_timeout" : milliseconds (thousandths) a
|
||||
connection is given to
|
||||
authenticate
|
||||
"pending_fd_timeout" : milliseconds (thousandths) a
|
||||
fd is given to be transmitted to
|
||||
dbus-daemon before disconnecting the
|
||||
connection
|
||||
"max_completed_connections" : max number of authenticated connections
|
||||
"max_incomplete_connections" : max number of unauthenticated
|
||||
connections
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue