diff options
author | Ray Strode <rstrode@redhat.com> | 2012-06-19 12:02:24 -0400 |
---|---|---|
committer | Ray Strode <rstrode@redhat.com> | 2012-06-28 11:27:05 -0400 |
commit | 26213aa0e0d8dca5f36cc23f6942525224cbe9f5 (patch) | |
tree | 85683230a95efc53f9bf3b76fc95c928fb21c702 | |
parent | 5e2f077e97a752092a31756eb6b3df03bc119c3d (diff) |
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.
-rw-r--r-- | src/util.c | 37 |
1 files changed, 26 insertions, 11 deletions
@@ -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; } |