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 19:22:47 +0100
commit01e32d6ddcfdcbd63cf1c8053f6e5d2ffdfbaa91 (patch)
tree7b4f35a0e4035883f08ff55b4d37f2bc1bb223d5
parent52abb5172f7426bb3f1dbe63a2b3a2d2ea7e7ac2 (diff)
downloaddbus-01e32d6ddcfdcbd63cf1c8053f6e5d2ffdfbaa91.tar.gz
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> (cherry picked from commit 8021fd84267ee1394d96f4a119adb57de3971a62) Conflicts: dbus/dbus-message.c
-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 f5edf3ca..badeabfb 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 07a9ebf1..e1068e34 100644
--- a/dbus/dbus-connection.c
+++ b/dbus/dbus-connection.c
@@ -2543,6 +2543,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 de03edd4..76540f42 100644
--- a/dbus/dbus-message-internal.h
+++ b/dbus/dbus-message-internal.h
@@ -98,6 +98,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 5d70f69d..43cb1be4 100644
--- a/dbus/dbus-message.c
+++ b/dbus/dbus-message.c
@@ -3984,6 +3984,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
@@ -4131,6 +4134,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;
@@ -4443,6 +4449,25 @@ _dbus_message_loader_get_pending_fds_count (DBusMessageLoader *loader)
}
/**
+ * 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
+}
+
+/**
* Allocates an integer ID to be used for storing application-specific
* data on any DBusMessage. The allocated ID may then be used
* with dbus_message_set_data() and dbus_message_get_data().
diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c
index e4d03c11..9846cc68 100644
--- a/dbus/dbus-transport.c
+++ b/dbus/dbus-transport.c
@@ -1502,6 +1502,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 6a3a8b3f..0d5a6e52 100644
--- a/dbus/dbus-transport.h
+++ b/dbus/dbus-transport.h
@@ -97,6 +97,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,