[sysprof] perf: avoid authorization dialog when user owns target pid



commit 9c6cec9b49766bf77c1713bc5a7c6d651e628068
Author: Christian Hergert <christian hergert me>
Date:   Mon Apr 25 15:11:54 2016 -0700

    perf: avoid authorization dialog when user owns target pid
    
    If we check the UID of the pid from /proc/pid/status and the UID matches
    our current user, we should be able to forego the authorization dialog.
    
    This should fix a regression where sysprof worked from jhbuild when
    profiling a process you have access to.

 lib/sp-perf-source.c |   96 +++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 91 insertions(+), 5 deletions(-)
---
diff --git a/lib/sp-perf-source.c b/lib/sp-perf-source.c
index 6da589b..70e0bb0 100644
--- a/lib/sp-perf-source.c
+++ b/lib/sp-perf-source.c
@@ -43,8 +43,11 @@
 #include <glib/gi18n.h>
 #include <errno.h>
 #include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
 
 #include "sp-clock.h"
+#include "sp-line-reader.h"
 #include "sp-perf-counter.h"
 #include "sp-perf-source.h"
 
@@ -449,6 +452,15 @@ sp_perf_source_add_pid (SpSource *source,
 }
 
 static void
+sp_perf_source_emit_ready (SpPerfSource *self)
+{
+  g_assert (SP_IS_PERF_SOURCE (self));
+
+  self->is_ready = TRUE;
+  sp_source_emit_ready (SP_SOURCE (self));
+}
+
+static void
 sp_perf_source_authorize_cb (GObject      *object,
                              GAsyncResult *result,
                              gpointer      user_data)
@@ -467,9 +479,80 @@ sp_perf_source_authorize_cb (GObject      *object,
         }
     }
 
-  self->is_ready = TRUE;
+  sp_perf_source_emit_ready (self);
+}
 
-  sp_source_emit_ready (SP_SOURCE (self));
+static gboolean
+user_owns_pid (uid_t uid,
+               GPid  pid)
+{
+  g_autofree gchar *contents = NULL;
+  g_autofree gchar *path = NULL;
+  g_autoptr(SpLineReader) reader = NULL;
+  gchar *line;
+  gsize len;
+  gsize line_len;
+
+  path = g_strdup_printf ("/proc/%u/status", (guint)pid);
+
+  if (!g_file_get_contents (path, &contents, &len, NULL))
+    return FALSE;
+
+  reader = sp_line_reader_new (contents, len);
+
+  while (NULL != (line = (gchar *)sp_line_reader_next (reader, &line_len)))
+    {
+      if (g_str_has_prefix (line, "Uid:"))
+        {
+          g_auto(GStrv) parts = NULL;
+          guint i;
+
+          line[line_len] = '\0';
+          parts = g_strsplit (line, "\t", 0);
+
+          for (i = 1; parts[i]; i++)
+            {
+              gint64 v64;
+
+              v64 = g_ascii_strtoll (parts[i], NULL, 10);
+
+              if (v64 > 0 && v64 <= G_MAXUINT)
+                {
+                  if ((uid_t)v64 == uid)
+                    return TRUE;
+                }
+            }
+        }
+    }
+
+  return FALSE;
+}
+
+static gboolean
+sp_perf_source_needs_auth (SpPerfSource *self)
+{
+  GHashTableIter iter;
+  gpointer key;
+  uid_t uid;
+
+  g_assert (SP_IS_PERF_SOURCE (self));
+
+  if (g_hash_table_size (self->pids) == 0)
+    return TRUE;
+
+  uid = getuid ();
+
+  g_hash_table_iter_init (&iter, self->pids);
+
+  while (g_hash_table_iter_next (&iter, &key, NULL))
+    {
+      GPid pid = GPOINTER_TO_INT (key);
+
+      if (!user_owns_pid (uid, pid))
+        return TRUE;
+    }
+
+  return FALSE;
 }
 
 static void
@@ -479,9 +562,12 @@ sp_perf_source_prepare (SpSource *source)
 
   g_assert (SP_IS_PERF_SOURCE (self));
 
-  sp_perf_counter_authorize_async (NULL,
-                                   sp_perf_source_authorize_cb,
-                                   g_object_ref (self));
+  if (sp_perf_source_needs_auth (self))
+    sp_perf_counter_authorize_async (NULL,
+                                     sp_perf_source_authorize_cb,
+                                     g_object_ref (self));
+  else
+    sp_perf_source_emit_ready (self);
 }
 
 static gboolean


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]