Fix accessibility of root apps on Linux
authorMike Gorse <mgorse@novell.com>
Tue, 8 Mar 2011 21:45:09 +0000 (15:45 -0600)
committerMike Gorse <mgorse@novell.com>
Tue, 8 Mar 2011 22:17:07 +0000 (16:17 -0600)
For an application running as root, check the uid of its parent, and, if
necessary, the parent's parent and so on, to find the user that initially
launched the application, and permit dbus connections from this uid.  Note
that this will likely only work under Linux.

atk-adaptor/bridge.c

index da844d8..940d244 100644 (file)
@@ -22,6 +22,7 @@
  * Boston, MA 02111-1307, USA.
  */
 
  * Boston, MA 02111-1307, USA.
  */
 
+#define _GNU_SOURCE
 #include "config.h"
 #include "dbus/dbus-glib-lowlevel.h"
 
 #include "config.h"
 #include "dbus/dbus-glib-lowlevel.h"
 
@@ -509,11 +510,54 @@ install_plug_hooks ()
   socket_class->embed = socket_embed_hook;
 }
 
   socket_class->embed = socket_embed_hook;
 }
 
+static uint
+get_ancestral_uid (uint pid)
+{
+  FILE *fp;
+  char buf [80];
+  int ppid = 0;
+  int uid = 0;
+  gboolean got_ppid = 0;
+  gboolean got_uid = 0;
+
+  sprintf (buf, "/proc/%d/status", pid);
+  fp = fopen (buf, "r");
+  if (!fp)
+    return 0;
+  while ((!got_ppid || !got_uid) && fgets (buf, sizeof (buf), fp))
+  {
+    if (sscanf (buf, "PPid:\t%d", &ppid) == 1)
+      got_ppid = TRUE;
+    else if (sscanf (buf, "Uid:\t%d", &uid) == 1)
+      got_uid = TRUE;
+  }
+  fclose (fp);
+
+  if (!got_ppid || !got_uid)
+    return 0;
+  if (uid != 0)
+    return uid;
+  if (ppid == 0 || ppid == 1)
+    return 0;
+  return get_ancestral_uid (ppid);
+}
+
+static dbus_bool_t
+user_check (DBusConnection *bus, unsigned long uid)
+{
+  if (uid == getuid () || uid == geteuid ())
+    return TRUE;
+  if (getuid () == 0)
+    return get_ancestral_uid (getpid ()) == uid;
+  return FALSE;
+}
+
 static void
 new_connection_cb (DBusServer *server, DBusConnection *con, void *data)
 {
   GList *new_list;
 
 static void
 new_connection_cb (DBusServer *server, DBusConnection *con, void *data)
 {
   GList *new_list;
 
+  dbus_connection_set_unix_user_function (con, user_check, NULL, NULL);
   dbus_connection_ref(con);
   dbus_connection_setup_with_g_main(con, NULL);
   droute_intercept_dbus (con);
   dbus_connection_ref(con);
   dbus_connection_setup_with_g_main(con, NULL);
   droute_intercept_dbus (con);