Comment by unwind

Comment by unwind 3 days ago

5 replies

I got exactly this far:

    uint8_t *data = (void *)(long)ctx->data;
before I stopped reading. I had to go look up the struct xdp_md [1], it is declared like this:

    struct xdp_md {
        __u32 data;
        __u32 data_end;
        __u32 data_meta;
        /* ... further fields elided ... */
    };
So clearly the `data` member is already an integer. The sane way to cast it would be to cast to the actual desired destination type, rather than first to some other random integer and then to a `void` pointer.

Like so:

    uint8_t * const data = (uint8_t *) ctx->data;
I added the `const` since the pointer value is not supposed to change, since we got it from the incoming structure. Note that that `const` does not mean we can't write to `data` if we feel like it, it means the base pointer itself can't change, we can't "re-point" the pointer. This is often a nice property, of course.

[1]: https://elixir.bootlin.com/linux/v6.17/source/include/uapi/l...

ziml77 2 days ago

Your code emits a compiler warning about casting an integer to a pointer. Changing the cast to void* emits a slightly different warning about the size of integer being cast to a pointer being smaller than the pointer type. Casting to a long and then a void* avoids both of these warnings.

  • fn-mote 12 hours ago

    Sorry, all that stuff might be true but this whole process is nuts.

    The code segment containing that code looks like a no-op.

    The rest of the post seems sane and well informed, so my theory is that this is a C / packet filtering idiom I’m not aware of, working far from that field.

    Otherwise I’m already freaked out by treating a 32 bit field as a pointer… even if you extend it to first.

    • foxmoss 11 hours ago

      > Otherwise I’m already freaked out by treating a 32 bit field as a pointer… even if you extend it to first.

      The cast from a 32 bit pointer to a 64 bit pointer is in fact an eBPF oddity. So what's happening here is that the virtual machine is just giving us a fake memory address just to use in the program and when the read actually needs to happen the kernel just rewrites the virtual addresses to the real ones. I'm assuming this is just a byproduct of the memory separation that eBPF does to prevent filters from accidentally reading kernel memory.

      Also yes the double cast is just to keep the compiler from throwing a warning.

    • mbac32768 11 hours ago

      Yeah it's freaky. It's C code but it targets the eBPF virtual machine.

baobun 8 hours ago

Possibly stupid question: Why does the author use different types for data and data_end in their struct?