Commit 66c15a41 authored by Simon McVittie's avatar Simon McVittie

Merge branch 'dbus-1.10'

parents db2af882 50fb0102
...@@ -20,10 +20,54 @@ Fixes: ...@@ -20,10 +20,54 @@ Fixes:
<includedir>, apply the same relocation as for the Exec paths <includedir>, apply the same relocation as for the Exec paths
in .service files (fd.o #92028, Simon McVittie) in .service files (fd.o #92028, Simon McVittie)
• On Unix when running tests as root, don't assert that root and
the dbus-daemon user can still call UpdateActivationEnvironment;
assert that those privileged users can call BecomeMonitor instead
(fd.o #93036, Simon McVittie)
• On Windows, fix a memory leak in the autolaunch transport (fd.o #92899,
Simon McVittie)
• On Windows Autotools builds, don't run tests that rely on
dbus-run-session and other Unix-specifics (fd.o #92899, Simon McVittie)
D-Bus 1.10.4 (2015-11-17)
==
The “Frostburn Canyon” release.
Enhancements:
• GetConnectionCredentials, GetConnectionUnixUser and
GetConnectionUnixProcessID with argument "org.freedesktop.DBus"
will now return details of the dbus-daemon itself. This is required
to be able to call SetEnvironment on systemd.
(fd.o #92857, Jan Alexander Steffens)
Fixes:
• Make UpdateActivationEnvironment always fail with AccessDenied on the
system bus. Previously, it was possible to configure it so root could
call it, but the environment variables were not actually used,
because the launch helper would discard them.
(fd.o #92857, Jan Alexander Steffens)
• On Unix with --systemd-activation on a user bus, make
UpdateActivationEnvironment pass on its arguments to systemd's
SetEnvironment method, solving inconsistency between the environments
used for traditional activation and systemd user-service activation.
(fd.o #92857, Jan Alexander Steffens)
• On Windows, don't crash if <syslog/> or --syslog is used • On Windows, don't crash if <syslog/> or --syslog is used
(fd.o #92538, Ralf Habacker) (fd.o #92538, Ralf Habacker)
• On Windows, fix various failing tests: • On Windows, fix a memory leak when setting a DBusError from a Windows
error (fd.o #92721, Ralf Habacker)
• On Windows, don't go into infinite recursion if we abort the process
with backtraces enabled (fd.o #92721, Ralf Habacker)
• Fix various failing tests, variously on Windows and cross-platform:
· don't test system.conf features (users, groups) that only make sense · don't test system.conf features (users, groups) that only make sense
on the system bus, which is not supported on Windows on the system bus, which is not supported on Windows
· don't call _dbus_warn() when we skip a test, since it is fatal · don't call _dbus_warn() when we skip a test, since it is fatal
...@@ -33,7 +77,8 @@ Fixes: ...@@ -33,7 +77,8 @@ Fixes:
· don't stress-test refcounting under Wine, where it's really slow · don't stress-test refcounting under Wine, where it's really slow
· stop assuming that a message looped-back to the test will be received · stop assuming that a message looped-back to the test will be received
immediately immediately
(fd.o #83539, #92538, fd.o #92721; Ralf Habacker, Simon McVittie) · skip some system bus tests on Windows since they make no sense there
(fd.o #92538, fd.o #92721; Ralf Habacker, Simon McVittie)
D-Bus 1.10.2 (2015-10-26) D-Bus 1.10.2 (2015-10-26)
== ==
......
...@@ -43,6 +43,13 @@ ...@@ -43,6 +43,13 @@
#include <dbus/dbus-marshal-validate.h> #include <dbus/dbus-marshal-validate.h>
#include <string.h> #include <string.h>
typedef enum
{
BUS_DRIVER_FOUND_SELF,
BUS_DRIVER_FOUND_PEER,
BUS_DRIVER_FOUND_ERROR,
} BusDriverFound;
static inline const char * static inline const char *
nonnull (const char *maybe_null, nonnull (const char *maybe_null,
const char *if_null) const char *if_null)
...@@ -68,11 +75,12 @@ bus_driver_get_owner_of_name (DBusConnection *connection, ...@@ -68,11 +75,12 @@ bus_driver_get_owner_of_name (DBusConnection *connection,
return bus_service_get_primary_owners_connection (serv); return bus_service_get_primary_owners_connection (serv);
} }
static DBusConnection * static BusDriverFound
bus_driver_get_conn_helper (DBusConnection *connection, bus_driver_get_conn_helper (DBusConnection *connection,
DBusMessage *message, DBusMessage *message,
const char *what_we_want, const char *what_we_want,
const char **name_p, const char **name_p,
DBusConnection **peer_conn_p,
DBusError *error) DBusError *error)
{ {
DBusConnection *conn; DBusConnection *conn;
...@@ -81,11 +89,17 @@ bus_driver_get_conn_helper (DBusConnection *connection, ...@@ -81,11 +89,17 @@ bus_driver_get_conn_helper (DBusConnection *connection,
if (!dbus_message_get_args (message, error, if (!dbus_message_get_args (message, error,
DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID)) DBUS_TYPE_INVALID))
return NULL; return BUS_DRIVER_FOUND_ERROR;
_dbus_assert (name != NULL); _dbus_assert (name != NULL);
_dbus_verbose ("asked for %s of connection %s\n", what_we_want, name); _dbus_verbose ("asked for %s of connection %s\n", what_we_want, name);
if (name_p != NULL)
*name_p = name;
if (strcmp (name, DBUS_SERVICE_DBUS) == 0)
return BUS_DRIVER_FOUND_SELF;
conn = bus_driver_get_owner_of_name (connection, name); conn = bus_driver_get_owner_of_name (connection, name);
if (conn == NULL) if (conn == NULL)
...@@ -93,13 +107,13 @@ bus_driver_get_conn_helper (DBusConnection *connection, ...@@ -93,13 +107,13 @@ bus_driver_get_conn_helper (DBusConnection *connection,
dbus_set_error (error, DBUS_ERROR_NAME_HAS_NO_OWNER, dbus_set_error (error, DBUS_ERROR_NAME_HAS_NO_OWNER,
"Could not get %s of name '%s': no such name", "Could not get %s of name '%s': no such name",
what_we_want, name); what_we_want, name);
return NULL; return BUS_DRIVER_FOUND_ERROR;
} }
if (name_p != NULL) if (peer_conn_p != NULL)
*name_p = name; *peer_conn_p = conn;
return conn; return BUS_DRIVER_FOUND_PEER;
} }
/* /*
...@@ -978,6 +992,72 @@ send_ack_reply (DBusConnection *connection, ...@@ -978,6 +992,72 @@ send_ack_reply (DBusConnection *connection,
return TRUE; return TRUE;
} }
/*
* Send a message from the driver, activating the destination if necessary.
* The message must already have a destination set.
*/
static dbus_bool_t
bus_driver_send_or_activate (BusTransaction *transaction,
DBusMessage *message,
DBusError *error)
{
BusContext *context;
BusService *service;
const char *service_name;
DBusString service_string;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
service_name = dbus_message_get_destination (message);
_dbus_assert (service_name != NULL);
_dbus_string_init_const (&service_string, service_name);
context = bus_transaction_get_context (transaction);
service = bus_registry_lookup (bus_context_get_registry (context),
&service_string);
if (service == NULL)
{
/* destination isn't connected yet; pass the message to activation */
BusActivation *activation;
activation = bus_context_get_activation (context);
if (!bus_transaction_capture (transaction, NULL, NULL, message))
{
BUS_SET_OOM (error);
_dbus_verbose ("No memory for bus_transaction_capture()");
return FALSE;
}
if (!bus_activation_activate_service (activation, NULL, transaction, TRUE,
message, service_name, error))
{
_DBUS_ASSERT_ERROR_IS_SET (error);
_dbus_verbose ("bus_activation_activate_service() failed");
return FALSE;
}
}
else
{
DBusConnection *service_conn;
service_conn = bus_service_get_primary_owners_connection (service);
if (!bus_transaction_send_from_driver (transaction, service_conn, message))
{
BUS_SET_OOM (error);
_dbus_verbose ("No memory for bus_transaction_send_from_driver()");
return FALSE;
}
}
return TRUE;
}
static dbus_bool_t static dbus_bool_t
bus_driver_handle_update_activation_environment (DBusConnection *connection, bus_driver_handle_update_activation_environment (DBusConnection *connection,
BusTransaction *transaction, BusTransaction *transaction,
...@@ -986,6 +1066,7 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection, ...@@ -986,6 +1066,7 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection,
{ {
dbus_bool_t retval; dbus_bool_t retval;
BusActivation *activation; BusActivation *activation;
BusContext *context;
DBusMessageIter iter; DBusMessageIter iter;
DBusMessageIter dict_iter; DBusMessageIter dict_iter;
DBusMessageIter dict_entry_iter; DBusMessageIter dict_entry_iter;
...@@ -993,6 +1074,8 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection, ...@@ -993,6 +1074,8 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection,
int key_type; int key_type;
DBusList *keys, *key_link; DBusList *keys, *key_link;
DBusList *values, *value_link; DBusList *values, *value_link;
DBusMessage *systemd_message;
DBusMessageIter systemd_iter;
_DBUS_ASSERT_ERROR_IS_CLEAR (error); _DBUS_ASSERT_ERROR_IS_CLEAR (error);
...@@ -1011,6 +1094,16 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection, ...@@ -1011,6 +1094,16 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection,
} }
#endif #endif
context = bus_connection_get_context (connection);
if (bus_context_get_servicehelper (context) != NULL)
{
dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
"Cannot change activation environment "
"on a system bus.");
return FALSE;
}
activation = bus_connection_get_activation (connection); activation = bus_connection_get_activation (connection);
dbus_message_iter_init (message, &iter); dbus_message_iter_init (message, &iter);
...@@ -1023,6 +1116,7 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection, ...@@ -1023,6 +1116,7 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection,
dbus_message_iter_recurse (&iter, &dict_iter); dbus_message_iter_recurse (&iter, &dict_iter);
retval = FALSE; retval = FALSE;
systemd_message = NULL;
/* Then loop through the sent dictionary, add the location of /* Then loop through the sent dictionary, add the location of
* the environment keys and values to lists. The result will * the environment keys and values to lists. The result will
...@@ -1077,6 +1171,33 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection, ...@@ -1077,6 +1171,33 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection,
_dbus_assert (_dbus_list_get_length (&keys) == _dbus_list_get_length (&values)); _dbus_assert (_dbus_list_get_length (&keys) == _dbus_list_get_length (&values));
if (bus_context_get_systemd_activation (bus_connection_get_context (connection)))
{
/* Prepare a call to forward environment updates to systemd */
systemd_message = dbus_message_new_method_call ("org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"SetEnvironment");
if (systemd_message == NULL ||
!dbus_message_set_sender (systemd_message, DBUS_SERVICE_DBUS))
{
BUS_SET_OOM (error);
_dbus_verbose ("No memory to create systemd message\n");
goto out;
}
dbus_message_set_no_reply (systemd_message, TRUE);
dbus_message_iter_init_append (systemd_message, &iter);
if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s",
&systemd_iter))
{
BUS_SET_OOM (error);
_dbus_verbose ("No memory to open systemd message container\n");
goto out;
}
}
key_link = keys; key_link = keys;
value_link = values; value_link = values;
while (key_link != NULL) while (key_link != NULL)
...@@ -1089,11 +1210,41 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection, ...@@ -1089,11 +1210,41 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection,
if (!bus_activation_set_environment_variable (activation, if (!bus_activation_set_environment_variable (activation,
key, value, error)) key, value, error))
{ {
_DBUS_ASSERT_ERROR_IS_SET (error); _DBUS_ASSERT_ERROR_IS_SET (error);
_dbus_verbose ("bus_activation_set_environment_variable() failed\n"); _dbus_verbose ("bus_activation_set_environment_variable() failed\n");
break; break;
} }
if (systemd_message != NULL)
{
DBusString envline;
const char *s;
/* SetEnvironment wants an array of KEY=VALUE strings */
if (!_dbus_string_init (&envline) ||
!_dbus_string_append_printf (&envline, "%s=%s", key, value))
{
BUS_SET_OOM (error);
_dbus_verbose ("No memory to format systemd environment line\n");
_dbus_string_free (&envline);
break;
}
s = _dbus_string_get_data (&envline);
if (!dbus_message_iter_append_basic (&systemd_iter,
DBUS_TYPE_STRING, &s))
{
BUS_SET_OOM (error);
_dbus_verbose ("No memory to append systemd environment line\n");
_dbus_string_free (&envline);
break;
}
_dbus_string_free (&envline);
}
key_link = _dbus_list_get_next_link (&keys, key_link); key_link = _dbus_list_get_next_link (&keys, key_link);
value_link = _dbus_list_get_next_link (&values, value_link); value_link = _dbus_list_get_next_link (&values, value_link);
} }
...@@ -1103,7 +1254,28 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection, ...@@ -1103,7 +1254,28 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection,
* matter, so we're punting for now. * matter, so we're punting for now.
*/ */
if (key_link != NULL) if (key_link != NULL)
goto out; {
if (systemd_message != NULL)
dbus_message_iter_abandon_container (&iter, &systemd_iter);
goto out;
}
if (systemd_message != NULL)
{
if (!dbus_message_iter_close_container (&iter, &systemd_iter))
{
BUS_SET_OOM (error);
_dbus_verbose ("No memory to close systemd message container\n");
goto out;
}
if (!bus_driver_send_or_activate (transaction, systemd_message, error))
{
_DBUS_ASSERT_ERROR_IS_SET (error);
_dbus_verbose ("bus_driver_send_or_activate() failed\n");
goto out;
}
}
if (!send_ack_reply (connection, transaction, if (!send_ack_reply (connection, transaction,
message, error)) message, error))
...@@ -1112,6 +1284,8 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection, ...@@ -1112,6 +1284,8 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection,
retval = TRUE; retval = TRUE;
out: out:
if (systemd_message != NULL)
dbus_message_unref (systemd_message);
_dbus_list_clear (&keys); _dbus_list_clear (&keys);
_dbus_list_clear (&values); _dbus_list_clear (&values);
return retval; return retval;
...@@ -1442,25 +1616,31 @@ bus_driver_handle_get_connection_unix_user (DBusConnection *connection, ...@@ -1442,25 +1616,31 @@ bus_driver_handle_get_connection_unix_user (DBusConnection *connection,
{ {
DBusConnection *conn; DBusConnection *conn;
DBusMessage *reply; DBusMessage *reply;
unsigned long uid; dbus_uid_t uid;
dbus_uint32_t uid32; dbus_uint32_t uid32;
const char *service; const char *service;
BusDriverFound found;
_DBUS_ASSERT_ERROR_IS_CLEAR (error); _DBUS_ASSERT_ERROR_IS_CLEAR (error);
reply = NULL; reply = NULL;
conn = bus_driver_get_conn_helper (connection, message, "UID", &service, found = bus_driver_get_conn_helper (connection, message, "UID", &service,
error); &conn, error);
switch (found)
if (conn == NULL) {
goto failed; case BUS_DRIVER_FOUND_SELF:
uid = _dbus_getuid ();
reply = dbus_message_new_method_return (message); break;
if (reply == NULL) case BUS_DRIVER_FOUND_PEER:
goto oom; if (!dbus_connection_get_unix_user (conn, &uid))
uid = DBUS_UID_UNSET;
break;
case BUS_DRIVER_FOUND_ERROR:
goto failed;
}
if (!dbus_connection_get_unix_user (conn, &uid)) if (uid == DBUS_UID_UNSET)
{ {
dbus_set_error (error, dbus_set_error (error,
DBUS_ERROR_FAILED, DBUS_ERROR_FAILED,
...@@ -1468,6 +1648,10 @@ bus_driver_handle_get_connection_unix_user (DBusConnection *connection, ...@@ -1468,6 +1648,10 @@ bus_driver_handle_get_connection_unix_user (DBusConnection *connection,
goto failed; goto failed;
} }
reply = dbus_message_new_method_return (message);
if (reply == NULL)
goto oom;
uid32 = uid; uid32 = uid;
if (! dbus_message_append_args (reply, if (! dbus_message_append_args (reply,
DBUS_TYPE_UINT32, &uid32, DBUS_TYPE_UINT32, &uid32,
...@@ -1499,25 +1683,31 @@ bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection, ...@@ -1499,25 +1683,31 @@ bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection,
{ {
DBusConnection *conn; DBusConnection *conn;
DBusMessage *reply; DBusMessage *reply;
unsigned long pid; dbus_pid_t pid;
dbus_uint32_t pid32; dbus_uint32_t pid32;
const char *service; const char *service;
BusDriverFound found;
_DBUS_ASSERT_ERROR_IS_CLEAR (error); _DBUS_ASSERT_ERROR_IS_CLEAR (error);
reply = NULL; reply = NULL;
conn = bus_driver_get_conn_helper (connection, message, "PID", &service, found = bus_driver_get_conn_helper (connection, message, "PID", &service,
error); &conn, error);
switch (found)
if (conn == NULL) {
goto failed; case BUS_DRIVER_FOUND_SELF:
pid = _dbus_getpid ();
reply = dbus_message_new_method_return (message); break;
if (reply == NULL) case BUS_DRIVER_FOUND_PEER:
goto oom; if (!dbus_connection_get_unix_process_id (conn, &pid))
pid = DBUS_PID_UNSET;
break;
case BUS_DRIVER_FOUND_ERROR:
goto failed;
}
if (!dbus_connection_get_unix_process_id (conn, &pid)) if (pid == DBUS_PID_UNSET)
{ {
dbus_set_error (error, dbus_set_error (error,
DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN, DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,
...@@ -1525,6 +1715,10 @@ bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection, ...@@ -1525,6 +1715,10 @@ bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection,
goto failed; goto failed;
} }
reply = dbus_message_new_method_return (message);
if (reply == NULL)
goto oom;
pid32 = pid; pid32 = pid;
if (! dbus_message_append_args (reply, if (! dbus_message_append_args (reply,
DBUS_TYPE_UINT32, &pid32, DBUS_TYPE_UINT32, &pid32,
...@@ -1559,22 +1753,29 @@ bus_driver_handle_get_adt_audit_session_data (DBusConnection *connection, ...@@ -1559,22 +1753,29 @@ bus_driver_handle_get_adt_audit_session_data (DBusConnection *connection,
void *data = NULL; void *data = NULL;
dbus_int32_t data_size; dbus_int32_t data_size;
const char *service; const char *service;
BusDriverFound found;
_DBUS_ASSERT_ERROR_IS_CLEAR (error); _DBUS_ASSERT_ERROR_IS_CLEAR (error);
reply = NULL; reply = NULL;
conn = bus_driver_get_conn_helper (connection, message, found = bus_driver_get_conn_helper (connection, message, "audit session data",
"audit session data", &service, error); &service, &conn, error);
if (conn == NULL) if (found == BUS_DRIVER_FOUND_ERROR)
goto failed; goto failed;
reply = dbus_message_new_method_return (message); reply = dbus_message_new_method_return (message);
if (reply == NULL) if (reply == NULL)
goto oom; goto oom;
if (!dbus_connection_get_adt_audit_session_data (conn, &data, &data_size) || data == NULL) /* We don't know how to find "ADT audit session data" for the bus daemon
* itself. Is that even meaningful?
* FIXME: Implement this or briefly note it makes no sense.
*/
if (found != BUS_DRIVER_FOUND_PEER ||
!dbus_connection_get_adt_audit_session_data (conn, &data, &data_size) ||
data == NULL)
{ {
dbus_set_error (error, dbus_set_error (error,
DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN, DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN,
...@@ -1614,22 +1815,28 @@ bus_driver_handle_get_connection_selinux_security_context (DBusConnection *conne ...@@ -1614,22 +1815,28 @@ bus_driver_handle_get_connection_selinux_security_context (DBusConnection *conne
DBusMessage *reply; DBusMessage *reply;
BusSELinuxID *context; BusSELinuxID *context;
const char *service; const char *service;
BusDriverFound found;
_DBUS_ASSERT_ERROR_IS_CLEAR (error); _DBUS_ASSERT_ERROR_IS_CLEAR (error);
reply = NULL; reply = NULL;
conn = bus_driver_get_conn_helper (connection, message, "security context", found = bus_driver_get_conn_helper (connection, message, "security context",
&service, error); &service, &conn, error);
if (conn == NULL) if (found == BUS_DRIVER_FOUND_ERROR)
goto failed; goto failed;
reply = dbus_message_new_method_return (message); reply = dbus_message_new_method_return (message);
if (reply == NULL) if (reply == NULL)
goto oom; goto oom;
context = bus_connection_get_selinux_id (conn); /* FIXME: Obtain the SELinux security context for the bus daemon itself */
if (found == BUS_DRIVER_FOUND_PEER)
context = bus_connection_get_selinux_id (conn);
else
context = NULL;
if (!context) if (!context)
{ {