[DTrace-devel] [PATCH v3 10/13] Add BPF helper mapping
Eugene Loh
eugene.loh at oracle.com
Thu Jul 28 00:06:22 UTC 2022
Reviewed-by: Eugene Loh <eugene.loh at oracle.com>
but it seems some earlier review remarks fell through the cracks. In any
case...
On 7/27/22 07:21, Kris Van Hees via DTrace-devel wrote:
> BPF helpers can be very specific to kernel versions, and the set of
> available helpers may differ between the system where DTrace was
> compiled and the system where it is being used.
>
> We add runtime checking of specific BPF helpers, with support for
> possible fallback hwlpers. E.g. if probe_read_user() is not found,
E.g., hwlpers.
> we can use probe_read() instead (though that may not guarantee
> successful execution).
That parenthetical remark strikes me as quite cryptic. One approach
would be to explain what probe_read* issues one is trying to address.
The other (I'm guessing based on previous remarks would be favored by
you) would simply be to omit the parenthetical remark: the scope of the
patch is to allow the implementation to refer to alternate helpers.
Whether or not they are suitable alternatives is beside the point.
> This can also be used to check whether certain helpers exist. By
> convention, when the BPF helper function id maps to 0, the helper is
> known not to be supported on the runtime system,
The paragraph ends in a comma. It should be a period.
But how about replacing the paragraph entirely? How about:
"When a helper does not exist and has no suitable alternative,
it can be mapped to BPF_FUNC_unspec."
>
> We include bpf.h for a kernel recent enough to support all the BPF
> features that DTrace can make use of.
>
> Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
> ---
>
>
> diff --git a/libdtrace/dt_bpf.c b/libdtrace/dt_bpf.c
> @@ -152,6 +152,65 @@ int dt_bpf_map_update(int fd, const void *key, const void *val)
> return bpf(BPF_MAP_UPDATE_ELEM, &attr);
> }
>
> +static int
> +have_helper(uint32_t func_id)
> +{
> + char log[DT_BPF_LOG_SIZE_SMALL] = { 0, };
> + char *ptr = &log[0];
> + struct bpf_insn insns[] = {
> + BPF_CALL_HELPER(func_id),
> + BPF_RETURN()
> + };
> + dtrace_difo_t dp;
> +
> + dp.dtdo_buf = insns;
> + dp.dtdo_len = ARRAY_SIZE(insns);
> +
> + /* If the program loads, we can use the helper. */
> + if (dt_bpf_prog_load(BPF_PROG_TYPE_KPROBE, &dp,
> + 1, log, DT_BPF_LOG_SIZE_SMALL) > 0)
If the program loads, it should be unloaded?
> + return 1;
> +
> + /* Permission denied -> helper not available to us */
> + if (errno == EPERM)
> + return 0;
> +
> + /* Sentinel to make the loop and string searches safe. */
> + log[DT_BPF_LOG_SIZE_SMALL - 2] = ' ';
> + log[DT_BPF_LOG_SIZE_SMALL - 1] = 0;
> +
> + while (*ptr == 0)
> + ptr++;
> +
> + /*
> + * If an 'invalid func' or 'unknown func' failure is reported, we
> + * cannot use the helper.
> + */
> + return strstr(ptr, "invalid func") == NULL &&
> + strstr(ptr, "unknown func") == NULL;
> +}
> +
> +void
> +dt_bpf_init_helpers(dtrace_hdl_t *dtp)
> +{
> + uint32_t i;
> +
> + /* Assume all helpers are available. */
> + for (i = 0; i < __BPF_FUNC_MAX_ID; i++)
> + dtp->dt_bpfhelper[i] = i;
> +
> + /* Verify the existance of some specific helpers. */
existence
> +#define BPF_HELPER_MAP(orig, alt) \
> + if (!have_helper(BPF_FUNC_##orig)) \
> + dtp->dt_bpfhelper[BPF_FUNC_##orig] = BPF_FUNC_##alt;
> +
> + BPF_HELPER_MAP(probe_read_user, probe_read);
> + BPF_HELPER_MAP(probe_read_user_str, probe_read_str);
> + BPF_HELPER_MAP(probe_read_kernel, probe_read);
> + BPF_HELPER_MAP(probe_read_kernel_str, probe_read_str);
> +#undef BPF_HELPER_MAP
> +}
> +
> static int
> create_gmap(dtrace_hdl_t *dtp, const char *name, enum bpf_map_type type,
> int ksz, int vsz, int size)
>
More information about the DTrace-devel
mailing list