summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlban Crequy <alban.crequy@collabora.co.uk>2014-07-18 17:28:32 +0100
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2014-09-15 12:30:30 +0100
commit8021fd84267ee1394d96f4a119adb57de3971a62 (patch)
tree06992c03cc5d687e33522cd92da5d4adab10eba6
parent995734750cea65012537748ee56488c707d2f027 (diff)
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=80559 Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
-rw-r--r--dbus/dbus-connection-internal.h5
-rw-r--r--dbus/dbus-connection.c16
-rw-r--r--dbus/dbus-message-internal.h3
-rw-r--r--dbus/dbus-message-private.h2
-rw-r--r--dbus/dbus-message.c25
-rw-r--r--dbus/dbus-transport.c16
-rw-r--r--dbus/dbus-transport.h3
7 files changed, 70 insertions, 0 deletions
diff --git a/dbus/dbus-connection-internal.h b/dbus/dbus-connection-internal.h
index 24e47725..28974040 100644
--- a/dbus/dbus-connection-internal.h
+++ b/dbus/dbus-connection-internal.h
@@ -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,
diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c
index 6aa24bc4..b574207d 100644
--- a/dbus/dbus-connection.c
+++ b/dbus/dbus-connection.c
@@ -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);
+}
+
/** @} */
/**
diff --git a/dbus/dbus-message-internal.h b/dbus/dbus-message-internal.h
index 45cb026e..e9a9ec01 100644
--- a/dbus/dbus-message-internal.h
+++ b/dbus/dbus-message-internal.h
@@ -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);
diff --git a/dbus/dbus-message-private.h b/dbus/dbus-message-private.h
index e1578abd..a611b095 100644
--- a/dbus/dbus-message-private.h
+++ b/dbus/dbus-message-private.h
@@ -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
};
diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c
index 59f3bdc8..3e74fc54 100644
--- a/dbus/dbus-message.c
+++ b/dbus/dbus-message.c
@@ -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));
diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c
index 690e5ba8..f63e0ced 100644
--- a/dbus/dbus-transport.c
+++ b/dbus/dbus-transport.c
@@ -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,
diff --git a/dbus/dbus-transport.h b/dbus/dbus-transport.h
index ff102f3a..39c74c46 100644
--- a/dbus/dbus-transport.h
+++ b/dbus/dbus-transport.h
@@ -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,