diff options
Diffstat (limited to 'bus')
-rw-r--r-- | bus/driver.c | 70 | ||||
-rw-r--r-- | bus/driver.h | 4 | ||||
-rw-r--r-- | bus/stats.c | 7 |
3 files changed, 79 insertions, 2 deletions
diff --git a/bus/driver.c b/bus/driver.c index e95a79d9..f5d3ebe2 100644 --- a/bus/driver.c +++ b/bus/driver.c @@ -878,6 +878,44 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection, _DBUS_ASSERT_ERROR_IS_CLEAR (error); + if (!bus_driver_check_message_is_for_us (message, error)) + return FALSE; + +#ifdef DBUS_UNIX + { + /* UpdateActivationEnvironment is basically a recipe for privilege + * escalation so let's be extra-careful: do not allow the sysadmin + * to shoot themselves in the foot. */ + unsigned long uid; + + if (!dbus_connection_get_unix_user (connection, &uid)) + { + bus_context_log (bus_transaction_get_context (transaction), + DBUS_SYSTEM_LOG_SECURITY, + "rejected attempt to call UpdateActivationEnvironment by " + "unknown uid"); + dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, + "rejected attempt to call UpdateActivationEnvironment by " + "unknown uid"); + return FALSE; + } + + /* On the system bus, we could in principle allow uid 0 to call + * UpdateActivationEnvironment; but they should know better anyway, + * and our default system.conf has always forbidden it */ + if (!_dbus_unix_user_is_process_owner (uid)) + { + bus_context_log (bus_transaction_get_context (transaction), + DBUS_SYSTEM_LOG_SECURITY, + "rejected attempt to call UpdateActivationEnvironment by uid %lu", + uid); + dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, + "rejected attempt to call UpdateActivationEnvironment"); + return FALSE; + } + } +#endif + activation = bus_connection_get_activation (connection); dbus_message_iter_init (message, &iter); @@ -1965,6 +2003,38 @@ bus_driver_handle_introspect (DBusConnection *connection, return FALSE; } +/* + * Set @error and return FALSE if the message is not directed to the + * dbus-daemon by its canonical object path. This is hardening against + * system services with poorly-written security policy files, which + * might allow sending dangerously broad equivalence classes of messages + * such as "anything with this assumed-to-be-safe object path". + * + * dbus-daemon is unusual in that it normally ignores the object path + * of incoming messages; we need to keep that behaviour for the "read" + * read-only method calls like GetConnectionUnixUser for backwards + * compatibility, but it seems safer to be more restrictive for things + * intended to be root-only or privileged-developers-only. + * + * It is possible that there are other system services with the same + * quirk as dbus-daemon. + */ +dbus_bool_t +bus_driver_check_message_is_for_us (DBusMessage *message, + DBusError *error) +{ + if (!dbus_message_has_path (message, DBUS_PATH_DBUS)) + { + dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, + "Method '%s' is only available at the canonical object path '%s'", + dbus_message_get_member (message), DBUS_PATH_DBUS); + + return FALSE; + } + + return TRUE; +} + dbus_bool_t bus_driver_handle_message (DBusConnection *connection, BusTransaction *transaction, diff --git a/bus/driver.h b/bus/driver.h index 713b2764..201709c4 100644 --- a/bus/driver.h +++ b/bus/driver.h @@ -46,7 +46,7 @@ dbus_bool_t bus_driver_send_service_owner_changed (const char *service_name BusTransaction *transaction, DBusError *error); dbus_bool_t bus_driver_generate_introspect_string (DBusString *xml); - - +dbus_bool_t bus_driver_check_message_is_for_us (DBusMessage *message, + DBusError *error); #endif /* BUS_DRIVER_H */ diff --git a/bus/stats.c b/bus/stats.c index 24308eb5..20321e5e 100644 --- a/bus/stats.c +++ b/bus/stats.c @@ -29,6 +29,7 @@ #include <dbus/dbus-connection-internal.h> #include "connection.h" +#include "driver.h" #include "services.h" #include "utils.h" @@ -49,6 +50,9 @@ bus_stats_handle_get_stats (DBusConnection *connection, _DBUS_ASSERT_ERROR_IS_CLEAR (error); + if (!bus_driver_check_message_is_for_us (message, error)) + return FALSE; + context = bus_transaction_get_context (transaction); connections = bus_context_get_connections (context); @@ -131,6 +135,9 @@ bus_stats_handle_get_connection_stats (DBusConnection *caller_connection, _DBUS_ASSERT_ERROR_IS_CLEAR (error); + if (!bus_driver_check_message_is_for_us (message, error)) + return FALSE; + registry = bus_connection_get_registry (caller_connection); if (! dbus_message_get_args (message, error, |