On Thu, 2023-01-26 at 11:03 -0800, Andrii Nakryiko wrote: > On Thu, Jan 26, 2023 at 3:41 AM Ilya Leoshkevich <iii@xxxxxxxxxxxxx> > wrote: > > > > On Wed, 2023-01-25 at 16:26 -0800, Andrii Nakryiko wrote: > > > On Wed, Jan 25, 2023 at 1:39 PM Ilya Leoshkevich > > > <iii@xxxxxxxxxxxxx> > > > wrote: > > > > > > > > Loading programs that use bpf_usdt_arg() on s390x fails with: > > > > > > > > ; switch (arg_spec->arg_type) { > > > > 139: (61) r1 = *(u32 *)(r2 +8) > > > > R2 unbounded memory access, make sure to bounds check any > > > > such > > > > access > > > > > > can you show a bit longer log? we shouldn't just use > > > bpf_probe_read_kernel for this. I suspect strategically placed > > > barrier_var() calls will solve this. This is usually an issue > > > with > > > compiler reordering operations and doing actual check after it > > > already > > > speculatively adjusted pointer (which is technically safe and ok > > > if > > > we > > > never deref that pointer, but verifier doesn't recognize such > > > pattern) > > > > The full log is here: > > > > https://gist.github.com/iii-i/b6149ee99b37078ec920ab1d3bb45134 [...] > > --- a/tools/lib/bpf/usdt.bpf.h > > +++ b/tools/lib/bpf/usdt.bpf.h > > @@ -130,7 +130,10 @@ int bpf_usdt_arg(struct pt_regs *ctx, __u64 > > arg_num, long *res) > > if (!spec) > > return -ESRCH; > > > > - if (arg_num >= BPF_USDT_MAX_ARG_CNT || arg_num >= spec- > > > arg_cnt) > > + if (arg_num >= BPF_USDT_MAX_ARG_CNT) > > + return -ENOENT; > > + barrier_var(arg_num); > > + if (arg_num >= spec->arg_cnt) > > return -ENOENT; > > > > arg_spec = &spec->args[arg_num]; > > > > I can use this in v2 if it looks good. > > arg_num -> spec->arg_cnt is "real" check, arg_num >= > BPF_USDT_MAX_ARG_CNT is more to satisfy verifier (we know that > spec->arg_cnt won't be >= BPF_USDT_MAX_ARG_CNT). Let's swap two > checks > in order and keep BPF_USDT_MAX_ARG_CNT close to spec->args[arg_num] > use? And if barrier_var() is necessary, then so be it. Unfortunately just swapping did not help, so let's use the barrier. > > Btw, I looked at the barrier_var() definition: > > > > #define barrier_var(var) asm volatile("" : "=r"(var) : "0"(var)) > > > > and I'm curious why it's not defined like this: > > > > #define barrier_var(var) asm volatile("" : "+r"(var)) > > > > which is a bit simpler? > > > > > no reason, just unfamiliarity with embedded asm back then, we can > update it we they are equivalent Thanks! I will add a simplification in v2 then.