XDP-Dynamic-Payload-Matching icon indicating copy to clipboard operation
XDP-Dynamic-Payload-Matching copied to clipboard

Section "methodfour" (FAIL)

Open doup123 opened this issue 4 years ago • 3 comments

I have faced a similar issue in the past, attempting to match the payload in a DNS packet. The problem there is that the qname (domain name) is of variable-length. To that end, I have used a BPF Map that matches the first 12 bytes of the name. I assume that the error that you see is related to the size of uint8_t hashkey[10]; I do not know exactly why but if you choose an array size that can be divided by 4, this may work e.g. uint8_t hashkey[12]. Have you tried different sizes of hashkey?

doup123 avatar Nov 28 '20 21:11 doup123

Hey and thank you for this report! I'm going to try this out next week at some point and I'll let you know how it goes.

gamemann avatar Dec 07 '20 01:12 gamemann

For example: I could compile a program that includes the following structure: Code struct key { u32 test0[125]; }; BPF_HASH(test_key,struct key,u64,1000);

doup123 avatar Dec 09 '20 15:12 doup123

Hey @doup123, I apologize for the delay on this! The last few months I've been extremely busy. I've been working on this project again today and I believe I finally got it to work. I'd recommend checking out the code here. This allows me to perform partial payload matching from the beginning of the payload. There isn't any support for exact payload matching at the moment since the map's key size would need to match the exact payload length.

I'm a little iffy on using the for loop in this situation due to performance, but I don't think there's any better way to do it.

uint8_t *pcktdata = data + sizeof(struct ethhdr) + (iph->ihl * 4) + l4len;

uint8_t hashkey[MAX_PAYLOAD_LENGTH] = {0};

for (int i = 0; i < MAX_PAYLOAD_LENGTH; i++)
{
    if (pcktdata + (i + 1) > (uint8_t *)data_end)
    {
        break;
    }

    //hashkey[i] = *(pcktdata + i)
    memcpy(hashkey + i, pcktdata + i, 1);
}

uint8_t *match = bpf_map_lookup_elem(&payload_map, &hashkey);

if (match)
{
    printk("Dropping matched packet.\n");
}

The MAX_PAYLOAD_LENGTH constant in the above example is 15 for a maximum of 15 bytes, but I'd imagine you can go a bit higher until you hit the max jump sequence limitation within BPF.

gamemann avatar Feb 27 '21 21:02 gamemann