Search code examples
cpointerspacketebpfxdp-bpf

Ebpf modify whole packet data


I am using XDP and trying to modify ctx->data. Let's say for this example, I want to set all the packet bytes to x+3 (x is a byte from the packet). Is that possible? I tried the following code and got errors from the verifier:

int xdp_start(struct xdp_md* ctx)
{
    void* data = (void*)(long)ctx->data;
    void* data_end = (void*)(long)ctx->data_end;
    uint32_t length = data_end - data;
    void* temp_data = data;
    size_t i = 0;
    #pragma unroll
    for(i=0; i < length; i++)
    {
        if ((__u8*)temp_data > (__u8*)data_end)
            break;
        *(__u8*)temp_data += (__u8)2;
        temp_data++;
     }
     return XDP_PASS;
}

It failed with “pointer arithmetic on pkt_end prohibited”

I also changed the for loop to:

for (i=0; i < length && i < 1500; i++)

To satisfy the verifier and make sure that this is not an infinite loop there is a way to not do that?

Also, I tried to set all packet bytes to a constant number:

*(__u8*)temp_data = 2;

And the verifier failed with:

A call to built-in function ‘memset’ is not supported.

When did I call memset?

In summary, I want to change each byte on the packet into another byte, is that possible? If yes I will be happy to know how.


Solution

  • Thank you all for your help! I used Andrew and pchaigno advice and the verifier still reject my program. Then I understood that my problem also was that I was incremented the pointer without checking it.

    int xdp_start(struct xdp_md* ctx)
    {
        void* data = (void*)(long)ctx->data;
        void* data_end = (void*)(long)ctx->data_end;
        uint32_t length = data_end - data;
        void* temp_data = data;
        size_t i = 0;
        #pragma unroll
        for(i=0; i < length; i++)
        {
            if ((__u8*)temp_data + 1 > (__u8*)data_end)
                break;
            *(__u8*)temp_data += (__u8)2;
            (__u8*)temp_data++;
         }
         return XDP_PASS;
    }
    

    Notice the change in the if, It should be + 1. Maybe the verifier does not even like that there is a variable that points to an out of bounds area.