Re: Problems with pointer offsets on ARM32

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Sep 15, 2020 at 12:26 AM Luka Oreskovic
<luka.oreskovic@xxxxxxxxxx> wrote:
>
> On Mon, Sep 14, 2020 at 7:49 PM Andrii Nakryiko
> <andrii.nakryiko@xxxxxxxxx> wrote:
> >
> > On Mon, Sep 14, 2020 at 12:55 AM Luka Oreskovic
> > <luka.oreskovic@xxxxxxxxxx> wrote:
> > >
> > > On Fri, Sep 11, 2020 at 8:14 PM Andrii Nakryiko
> > > <andrii.nakryiko@xxxxxxxxx> wrote:
> > > >
> > > > On Fri, Sep 11, 2020 at 9:45 AM Luka Oreskovic
> > > > <luka.oreskovic@xxxxxxxxxx> wrote:
> > > > >
> > > > > Greetings everyone,
> > > > >
> > > > > I have been testing various BPF programs on the ARM32 architecture and
> > > > > have encountered a strange error.
> > > > >
> > > > > When trying to run a simple program that prints out the arguments of
> > > > > the open syscall,
> > > > > I found some strange behaviour with the pointer offsets when accessing
> > > > > the arguments:
> > > > > The output of llvm-objdump differed from the verifier error dump log.
> > > > > Notice the differences in lines 0 and 1. Why is the bytecode being
> > > > > altered at runtime?
> > > > >
> > > > > I attached the program, the llvm-objdump result and the verifier dump below.
> > > > >
> > > > > Best wishes,
> > > > > Luka Oreskovic
> > > > >
> > > > > BPF program
> > > > > --------------------------------------------
> > > > > #include "vmlinux.h"
> > > > > #include <bpf/bpf_helpers.h>
> > > > >
> > > > > SEC("tracepoint/syscalls/sys_enter_open")
> > > > > int tracepoint__syscalls__sys_enter_open(struct trace_event_raw_sys_enter* ctx)
> > > > > {
> > > > >         const char *arg1 = (const char *)ctx->args[0];
> > > > >         int arg2 = (int)ctx->args[1];

Luka, can you apply the changes below to bpf_core_read.h header and
read these args using BPF_CORE_READ() macro:

const char *arg1 = (const char *)BPF_CORE_READ(ctx, args[0]);
int arg2 = BPF_CORE_READ(ctx, args[1]);

I'm curious if that will work (unfortunately I don't have a complete
enough setup to test this).

The patch is as follows (with broken tab<->space conversion, so please
make changes by hand):

diff --git a/tools/lib/bpf/bpf_core_read.h b/tools/lib/bpf/bpf_core_read.h
index bbcefb3ff5a5..fee6328d36c0 100644
--- a/tools/lib/bpf/bpf_core_read.h
+++ b/tools/lib/bpf/bpf_core_read.h
@@ -261,14 +261,16 @@ enum bpf_enum_value_kind {
 #define ___type(...) typeof(___arrow(__VA_ARGS__))

 #define ___read(read_fn, dst, src_type, src, accessor)                     \
-       read_fn((void *)(dst), sizeof(*(dst)), &((src_type)(src))->accessor)
+       read_fn((void *)(dst),                                              \
+               bpf_core_field_size(((src_type)(src))->accessor),           \
+               &((src_type)(src))->accessor)

 /* "recursively" read a sequence of inner pointers using local __t var */
 #define ___rd_first(src, a) ___read(bpf_core_read, &__t, ___type(src), src, a);
 #define ___rd_last(...)
             \
        ___read(bpf_core_read, &__t,                                        \
                ___type(___nolast(__VA_ARGS__)), __t, ___last(__VA_ARGS__));
-#define ___rd_p1(...) const void *__t; ___rd_first(__VA_ARGS__)
+#define ___rd_p1(...) const void *__t = (void *)0; ___rd_first(__VA_ARGS__)
 #define ___rd_p2(...) ___rd_p1(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__)
 #define ___rd_p3(...) ___rd_p2(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__)
 #define ___rd_p4(...) ___rd_p3(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__)



BTW, this approach should work for reading pointers as well, it would
be nice if you can test that as well. E.g., something like the
following:

struct task_struct *t = (void *)bpf_get_current_task();
int ppid = BPF_CORE_READ(t, group_leader, tgid);

If you try it without the patch above, it should either read garbage
or zero, but not a valid parent PID (please verify that as well).

I really appreciate your help with testing, thanks!


> > > > >
> > > > >         bpf_printk("Open arg 1: %s\n", arg1);
> > > > >         bpf_printk("Open arg 2: %d\n", arg2);
> > > > >
> > > > >         return 0;
> > > > > }
> > > > >
> > > > > char LICENSE[] SEC("license") = "GPL";
> > > > >
> > > > >

[...]

>
> Best wishes,
> Luka Oreskovic



[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux