简体   繁体   中英

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.

It failed with “pointer arithmetic on pkt_end prohibited”

As Andrew said in comments, you'll first have to declare temp_data as a __u8* to be able to run temp_data++ .

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

No, all loops have to have bounds known at compile time in BPF.

When did I call memset?

Check the compiled bytecode. Your compiler likely used memset for you, as an optimization for the loop.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM