<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
v2 on its way for this, fixing the lack of initialization of the log buffer.<br>
</div>
<div id="appendonsend"></div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> Kris Van Hees<br>
<b>Sent:</b> Wednesday, July 13, 2022 3:17 PM<br>
<b>To:</b> dtrace-devel@oss.oracle.com <dtrace-devel@oss.oracle.com><br>
<b>Subject:</b> [PATCH 09/12] Add BPF helper mapping</font>
<div> </div>
</div>
<div class="BodyFragment"><font size="2"><span style="font-size:11pt;">
<div class="PlainText">BPF helpers can be very specific to kernel versions, and the set of<br>
available helpers may differ between the system where DTrace was<br>
compiled and the system where it is being used.<br>
<br>
We add runtime checking of specific BPF helpers, with support for<br>
possible fallback hwlpers. E.g. if probe_read_user() is not found,<br>
we can use probe_read() instead (though that may not guarantee<br>
successful execution).<br>
<br>
This can also be used to check whether certain helpers exist. By<br>
convention, when the BPF helper function id maps to 0, the helper is<br>
known not to be supported on the runtime system,<br>
<br>
Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com><br>
---<br>
libdtrace/dt_bpf.c | 60 +++++++++++++++++++++++++++++++++++++++++++++<br>
libdtrace/dt_bpf.h | 1 +<br>
libdtrace/dt_impl.h | 1 +<br>
libdtrace/dt_open.c | 3 +++<br>
4 files changed, 65 insertions(+)<br>
<br>
diff --git a/libdtrace/dt_bpf.c b/libdtrace/dt_bpf.c<br>
index c008f624..269c6e1d 100644<br>
--- a/libdtrace/dt_bpf.c<br>
+++ b/libdtrace/dt_bpf.c<br>
@@ -152,6 +152,66 @@ int dt_bpf_map_update(int fd, const void *key, const void *val)<br>
return bpf(BPF_MAP_UPDATE_ELEM, &attr);<br>
}<br>
<br>
+static int<br>
+have_helper(uint32_t func_id)<br>
+{<br>
+ uint64_t logsz = 4096;<br>
+ char log[logsz];<br>
+ char *ptr = &log[0];<br>
+ struct bpf_insn insns[] = {<br>
+ BPF_CALL_HELPER(func_id),<br>
+ BPF_RETURN()<br>
+ };<br>
+ dtrace_difo_t dp;<br>
+<br>
+ dp.dtdo_buf = insns;<br>
+ dp.dtdo_len = ARRAY_SIZE(insns);<br>
+<br>
+ /* If the program loads, we can use the helper. */<br>
+ if (dt_bpf_prog_load(BPF_PROG_TYPE_KPROBE, &dp, 1, log, logsz) > 0)<br>
+ return 1;<br>
+<br>
+ /* Permission denied -> helper not available to us */<br>
+ if (errno == EPERM)<br>
+ return 0;<br>
+<br>
+ /*<br>
+ * Skip past leading 0-bytes, but ensure there is a sentinel so that<br>
+ * the loop is guaranteed to end.<br>
+ */<br>
+ log[logsz - 2] = 0;<br>
+ log[logsz - 1] = ' ';<br>
+ while (*ptr == 0)<br>
+ ptr++;<br>
+<br>
+ /*<br>
+ * If an 'invalid func' or 'unknown func' failure is reported, we<br>
+ * cannot use the helper.<br>
+ */<br>
+ return strstr(ptr, "invalid func") == NULL &&<br>
+ strstr(ptr, "unknown func") == NULL;;<br>
+}<br>
+<br>
+void<br>
+dt_bpf_init_helpers(dtrace_hdl_t *dtp)<br>
+{<br>
+ uint32_t i;<br>
+<br>
+ /* Assume all helpers are available. */<br>
+ for (i = 0; i < __BPF_FUNC_MAX_ID; i++)<br>
+ dtp->dt_bpfhelper[i] = i;<br>
+<br>
+ /* Verify the existance of some specific helpers. */<br>
+#define BPF_HELPER_MAP(orig, alt) \<br>
+ if (!have_helper(BPF_FUNC_##orig)) \<br>
+ dtp->dt_bpfhelper[BPF_FUNC_##orig] = BPF_FUNC_##alt;<br>
+ BPF_HELPER_MAP(probe_read_user, probe_read);<br>
+ BPF_HELPER_MAP(probe_read_user_str, probe_read_str);<br>
+ BPF_HELPER_MAP(probe_read_kernel, probe_read);<br>
+ BPF_HELPER_MAP(probe_read_kernel_str, probe_read_str);<br>
+#undef BPF_HELPER_MAP<br>
+}<br>
+<br>
static int<br>
create_gmap(dtrace_hdl_t *dtp, const char *name, enum bpf_map_type type,<br>
int ksz, int vsz, int size)<br>
diff --git a/libdtrace/dt_bpf.h b/libdtrace/dt_bpf.h<br>
index c4c6e717..fbff8437 100644<br>
--- a/libdtrace/dt_bpf.h<br>
+++ b/libdtrace/dt_bpf.h<br>
@@ -48,6 +48,7 @@ extern int dt_bpf_map_lookup(int fd, const void *key, void *val);<br>
extern int dt_bpf_map_update(int fd, const void *key, const void *val);<br>
extern int dt_bpf_map_delete(int fd, const void *key);<br>
extern int dt_bpf_load_progs(struct dtrace_hdl *, uint_t);<br>
+extern void dt_bpf_init_helpers(struct dtrace_hdl *dtp);<br>
<br>
#ifdef __cplusplus<br>
}<br>
diff --git a/libdtrace/dt_impl.h b/libdtrace/dt_impl.h<br>
index 747815ac..6e909dad 100644<br>
--- a/libdtrace/dt_impl.h<br>
+++ b/libdtrace/dt_impl.h<br>
@@ -376,6 +376,7 @@ struct dtrace_hdl {<br>
uint_t dt_treedump; /* dtrace tree debug bitmap (see below) */<br>
uint_t dt_disasm; /* dtrace disassembler bitmap (see below) */<br>
uint64_t dt_options[DTRACEOPT_MAX]; /* dtrace run-time options */<br>
+ uint32_t dt_bpfhelper[__BPF_FUNC_MAX_ID]; /* BPF helper mapping */<br>
int dt_version; /* library version requested by client */<br>
int dt_ctferr; /* error resulting from last CTF failure */<br>
int dt_errno; /* error resulting from last failed operation */<br>
diff --git a/libdtrace/dt_open.c b/libdtrace/dt_open.c<br>
index deea0781..fa8aade8 100644<br>
--- a/libdtrace/dt_open.c<br>
+++ b/libdtrace/dt_open.c<br>
@@ -28,6 +28,7 @@<br>
#include <libproc.h><br>
<br>
#include <dt_impl.h><br>
+#include <dt_bpf.h><br>
#include <dt_pcap.h><br>
#include <dt_program.h><br>
#include <dt_module.h><br>
@@ -1136,6 +1137,8 @@ dt_vopen(int version, int flags, int *errp,<br>
if (dtrace_setopt(dtp, "libdir", _dtrace_libdir) != 0)<br>
return set_open_errno(dtp, errp, dtp->dt_errno);<br>
<br>
+ dt_bpf_init_helpers(dtp);<br>
+<br>
return dtp;<br>
}<br>
<br>
-- <br>
2.34.1<br>
<br>
</div>
</span></font></div>
</body>
</html>