Commit 8021fd84 authored by Alban Crequy's avatar Alban Crequy Committed by Simon McVittie

DBusConnection: implements _dbus_connection_set_pending_fds_function

This is one of four commits needed to address CVE-2014-3637.

This will allow the bus to be notified whenever a file descriptor is added or
removed from a DBusConnection's DBusMessageLoader.

Bug: https://bugs.freedesktop.org/show_bug.cgi?id=80559Reviewed-by: default avatarSimon McVittie <simon.mcvittie@collabora.co.uk>
parent 99573475
......@@ -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);
......@@ -101,6 +103,9 @@ void _dbus_connection_test_get_locks (DBusConnectio
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,
......
......@@ -2560,6 +2560,22 @@ _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);
}
/** @} */
/**
......
......@@ -97,6 +97,9 @@ void _dbus_message_loader_set_max_message_unix_fds(DBusMessageLoad
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
};
......
......@@ -4059,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
......@@ -4206,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;
......@@ -4514,6 +4520,25 @@ _dbus_message_loader_get_pending_fds_count (DBusMessageLoader *loader)
#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));
......
......@@ -1523,6 +1523,22 @@ _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,
......
......@@ -98,6 +98,9 @@ dbus_bool_t _dbus_transport_set_auth_mechanisms (DBusTransport
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,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment