summaryrefslogtreecommitdiff
authorRay Strode <rstrode@redhat.com>2012-06-19 16:02:24 (GMT)
committer Ray Strode <rstrode@redhat.com>2012-06-28 15:27:05 (GMT)
commit26213aa0e0d8dca5f36cc23f6942525224cbe9f5 (patch) (side-by-side diff)
tree85683230a95efc53f9bf3b76fc95c928fb21c702
parent5e2f077e97a752092a31756eb6b3df03bc119c3d (diff)
downloadaccountsservice-26213aa0e0d8dca5f36cc23f6942525224cbe9f5.zip
accountsservice-26213aa0e0d8dca5f36cc23f6942525224cbe9f5.tar.gz
util: CVE-2012-2737: validate SetIconFile caller over bus
The AccountsService SetIconFile call associates an icon with a user. SetIconFile allows users to have icons visible at the login screen that don't necessarily originate in globally readable or always available locations. This is accomplished by copying the originating icon to the local disk in /var. Since AccountsService runs with with root privileges, the implemention of the SetIconFile method queries the uid of the method caller, forks, switches to that uid and performs the image copy as if it were the user. Unfortunately, the uid lookup peformed is done "just in time" instead of looking at peer credentials from the time the call was initiated. There is a race condition that means a caller could invoke the method call, quickly exec a setuid binary, and then cause the copy to be performed as the uid of the setuid process. This commit changes the uid lookup logic to query the system bus daemon for the peer credentials that were cached from the caller at the time of the initial connection.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--src/util.c37
1 files changed, 26 insertions, 11 deletions
diff --git a/src/util.c b/src/util.c
index 66ddd98..1ce375b 100644
--- a/src/util.c
+++ b/src/util.c
@@ -251,22 +251,37 @@ get_user_groups (const gchar *user,
gboolean
-get_caller_uid (GDBusMethodInvocation *context, gint *uid)
+get_caller_uid (GDBusMethodInvocation *context,
+ gint *uid)
{
- PolkitSubject *subject;
- PolkitSubject *process;
+ GVariant *reply;
+ GError *error;
+
+ error = NULL;
+ reply = g_dbus_connection_call_sync (g_dbus_method_invocation_get_connection (context),
+ "org.freedesktop.DBus",
+ "/org/freedesktop/DBus",
+ "org.freedesktop.DBus",
+ "GetConnectionUnixUser",
+ g_variant_new ("(s)",
+ g_dbus_method_invocation_get_sender (context)),
+ G_VARIANT_TYPE ("(u)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+
+ if (reply == NULL) {
+ g_warning ("Could not talk to message bus to find uid of sender %s: %s",
+ g_dbus_method_invocation_get_sender (context),
+ error->message);
+ g_error_free (error);
- subject = polkit_system_bus_name_new (g_dbus_method_invocation_get_sender (context));
- process = polkit_system_bus_name_get_process_sync (POLKIT_SYSTEM_BUS_NAME (subject), NULL, NULL);
- if (!process) {
- g_object_unref (subject);
return FALSE;
}
- *uid = polkit_unix_process_get_uid (POLKIT_UNIX_PROCESS (process));
-
- g_object_unref (subject);
- g_object_unref (process);
+ g_variant_get (reply, "(u)", uid);
+ g_variant_unref (reply);
return TRUE;
}