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