[sysprof] daemon: add API to get kernel symbols



commit 3162b407020980f358c57af1888b4a83ec08c5b1
Author: Christian Hergert <chergert redhat com>
Date:   Sun Jan 28 21:30:19 2018 -0800

    daemon: add API to get kernel symbols
    
    This is useful because we might not have access to kernel symbols from
    user applications which are not root. Various distributions are starting
    to censor kernel addresses without root.
    
    This allows the clients to fetch the symbol addresses without having to
    be root themselves.

 daemon/meson.build                |    9 +++-
 daemon/sysprofd.c                 |   90 ++++++++++++++++++++++++++++++++-----
 data/org.gnome.Sysprof2.xml       |   15 ++++++
 data/org.gnome.sysprof2.policy.in |   12 +++++
 4 files changed, 113 insertions(+), 13 deletions(-)
---
diff --git a/daemon/meson.build b/daemon/meson.build
index 81f2484..d0cf87c 100644
--- a/daemon/meson.build
+++ b/daemon/meson.build
@@ -4,16 +4,23 @@ sysprofd_sources = [
   'sysprofd.c',
   'sd-bus-helper.c',
   'sd-bus-helper.h',
+  '../lib/sp-kallsyms.c',
+  '../lib/sp-kallsyms.h',
 ]
 
 # NOTE: This is used in data/meson.build
 pkglibexecdir = join_paths(get_option('prefix'), get_option('libexecdir'), 'sysprof')
 
+sysprofd_deps = [
+  dependency('libsystemd', version: '>=222'),
+  dependency('glib-2.0'),
+]
+
 sysprofd = executable('sysprofd',
   sysprofd_sources,
   c_args: exe_c_args,
   link_args: exe_link_args,
-  dependencies: dependency('libsystemd', version: '>=222'),
+  dependencies: sysprofd_deps,
   install: true,
   install_dir: pkglibexecdir,
 )
diff --git a/daemon/sysprofd.c b/daemon/sysprofd.c
index 681cd63..8544ffe 100644
--- a/daemon/sysprofd.c
+++ b/daemon/sysprofd.c
@@ -16,13 +16,12 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
 
 #include <assert.h>
 #include <stdio.h>
 #include <errno.h>
+#include <glib.h>
 #include <linux/capability.h>
 #include <linux/perf_event.h>
 #include <stdlib.h>
@@ -31,9 +30,84 @@
 #include <unistd.h>
 
 #include "sd-bus-helper.h"
+#include "../lib/sp-kallsyms.h"
 
 #define BUS_TIMEOUT_USEC (1000000L * 10L)
 
+#if 0
+#define GOTO(l) do { \
+  fprintf (stderr, "GOTO: %s:%d: " #l "\n", __FUNCTION__, __LINE__); \
+  goto l; \
+} while (0)
+#else
+#define GOTO(l) goto l
+#endif
+
+static int
+sysprofd_get_kernel_symbols (sd_bus_message *msg,
+                             void           *user_data,
+                             sd_bus_error   *error)
+{
+  g_autoptr(SpKallsyms) kallsyms = NULL;
+  sd_bus_message *reply = NULL;
+  const gchar *name;
+  guint64 addr;
+  guint8 type;
+  bool challenge = false;
+  int r;
+
+  assert (msg);
+  assert (error);
+
+  /* Authorize peer */
+  r = bus_test_polkit (msg,
+                       CAP_SYS_ADMIN,
+                       "org.gnome.sysprof2.get-kernel-symbols",
+                       NULL,
+                       UID_INVALID,
+                       &challenge,
+                       error);
+
+  if (r <= 0)
+    fprintf (stderr, "GetKernelSymbols() Failure: %s\n", error->message);
+
+  if (r < 0)
+    return r;
+  else if (r == 0)
+    return -EACCES;
+
+  if (!(kallsyms = sp_kallsyms_new ()))
+    {
+      sd_bus_error_set (error,
+                        SD_BUS_ERROR_FILE_NOT_FOUND,
+                        "Failed to open /proc/kallsyms");
+      return -ENOENT;
+    }
+
+  r = sd_bus_message_new_method_return (msg, &reply);
+  if (r < 0)
+    return r;
+
+  r = sd_bus_message_open_container (reply, 'a', "(tys)");
+  if (r < 0)
+    return r;
+
+  while (sp_kallsyms_next (kallsyms, &name, &addr, &type))
+  {
+    g_print ("%s: %lu\n", name, addr);
+    sd_bus_message_append (reply, "(tys)", addr, type, name);
+  }
+
+  r = sd_bus_message_close_container (reply);
+  if (r < 0)
+    return r;
+
+  r = sd_bus_send (NULL, reply, NULL);
+  sd_bus_message_unref (reply);
+
+  return r;
+}
+
 static int
 _perf_event_open (struct perf_event_attr *attr,
                   pid_t                   pid,
@@ -50,15 +124,6 @@ _perf_event_open (struct perf_event_attr *attr,
   return syscall (__NR_perf_event_open, attr, pid, cpu, group_fd, flags);
 }
 
-#if 0
-#define GOTO(l) do { \
-  fprintf (stderr, "GOTO: %s:%d: " #l "\n", __FUNCTION__, __LINE__); \
-  goto l; \
-} while (0)
-#else
-#define GOTO(l) goto l
-#endif
-
 static int
 sysprofd_perf_event_open (sd_bus_message *msg,
                           void           *user_data,
@@ -274,6 +339,7 @@ sysprofd_perf_event_open (sd_bus_message *msg,
 static const sd_bus_vtable sysprofd_vtable[] = {
   SD_BUS_VTABLE_START (0),
   SD_BUS_METHOD ("PerfEventOpen", "a{sv}iit", "h", sysprofd_perf_event_open, SD_BUS_VTABLE_UNPRIVILEGED),
+  SD_BUS_METHOD ("GetKernelSymbols", "", "a(tys)", sysprofd_get_kernel_symbols, SD_BUS_VTABLE_UNPRIVILEGED),
   SD_BUS_VTABLE_END
 };
 
diff --git a/data/org.gnome.Sysprof2.xml b/data/org.gnome.Sysprof2.xml
index 46e87e1..b22de4f 100644
--- a/data/org.gnome.Sysprof2.xml
+++ b/data/org.gnome.Sysprof2.xml
@@ -20,5 +20,20 @@
    <arg name="flags" type="t" direction="in"/>
    <arg name="perf_stream_fd" type="h" direction="out"/>
   </method>
+
+  <!--
+    GetKernelSymbols:
+
+    Loads the name, type, and address of Linux kernel symbols. This is useful
+    if your system does not provide access to /proc/kallsyms to non-root users.
+
+    Returns: an array of (tys) tuples. t is the address, y is the type, and s
+      is the name.
+
+    Since: 3.28
+  -->
+  <method name="GetKernelSymbols">
+   <arg name="symbols" type="a(tys)" direction="out"/>
+  </method>
  </interface>
 </node>
diff --git a/data/org.gnome.sysprof2.policy.in b/data/org.gnome.sysprof2.policy.in
index 5ba36e1..7398a16 100644
--- a/data/org.gnome.sysprof2.policy.in
+++ b/data/org.gnome.sysprof2.policy.in
@@ -17,6 +17,18 @@
       <allow_inactive>auth_admin_keep</allow_inactive>
       <allow_active>auth_admin_keep</allow_active>
     </defaults>
+    <annotate key="org.freedesktop.policykit.imply">org.gnome.sysprof2.get-kernel-symbols</annotate>
+  </action>
+
+  <action id="org.gnome.sysprof2.get-kernel-symbols">
+    <description>Get a list of kernel symbols and their address</description>
+    <message>Authentication is required to access Linux kernel information.</message>
+    <defaults>
+      <allow_any>auth_admin_keep</allow_any>
+      <allow_inactive>auth_admin_keep</allow_inactive>
+      <allow_active>auth_admin_keep</allow_active>
+    </defaults>
+    <annotate key="org.freedesktop.policykit.imply">org.gnome.sysprof2.perf-event-open</annotate>
   </action>
 
 </policyconfig>


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