Commit 3eee1f75 authored by Daniel Borkmann's avatar Daniel Borkmann

bpf: fix bpf_skb_load_bytes_relative pkt length check

The len > skb_headlen(skb) cannot be used as a maximum upper bound
for the packet length since it does not have any relation to the full
linear packet length when filtering is used from upper layers (e.g.
in case of reuseport BPF programs) as by then skb->data, skb->len
already got mangled through __skb_pull() and others.

Fixes: 4e1ec56c ("bpf: add skb_load_bytes_relative helper")
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Acked-by: default avatarMartin KaFai Lau <kafai@fb.com>
parent b611da43
...@@ -1712,24 +1712,26 @@ static const struct bpf_func_proto bpf_skb_load_bytes_proto = { ...@@ -1712,24 +1712,26 @@ static const struct bpf_func_proto bpf_skb_load_bytes_proto = {
BPF_CALL_5(bpf_skb_load_bytes_relative, const struct sk_buff *, skb, BPF_CALL_5(bpf_skb_load_bytes_relative, const struct sk_buff *, skb,
u32, offset, void *, to, u32, len, u32, start_header) u32, offset, void *, to, u32, len, u32, start_header)
{ {
u8 *end = skb_tail_pointer(skb);
u8 *net = skb_network_header(skb);
u8 *mac = skb_mac_header(skb);
u8 *ptr; u8 *ptr;
if (unlikely(offset > 0xffff || len > skb_headlen(skb))) if (unlikely(offset > 0xffff || len > (end - mac)))
goto err_clear; goto err_clear;
switch (start_header) { switch (start_header) {
case BPF_HDR_START_MAC: case BPF_HDR_START_MAC:
ptr = skb_mac_header(skb) + offset; ptr = mac + offset;
break; break;
case BPF_HDR_START_NET: case BPF_HDR_START_NET:
ptr = skb_network_header(skb) + offset; ptr = net + offset;
break; break;
default: default:
goto err_clear; goto err_clear;
} }
if (likely(ptr >= skb_mac_header(skb) && if (likely(ptr >= mac && ptr + len <= end)) {
ptr + len <= skb_tail_pointer(skb))) {
memcpy(to, ptr, len); memcpy(to, ptr, len);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment