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.
This commit is contained in:
Christian Hergert
2018-01-28 21:30:19 -08:00
parent cf756c65aa
commit 3162b40702
4 changed files with 113 additions and 13 deletions

View File

@ -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,
)

View File

@ -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
};

View File

@ -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>

View File

@ -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>