summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorCong Wang <cong.wang@bytedance.com>2024-12-12 19:40:54 -0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-01-02 10:34:11 +0100
commit997cf2d8c206941b501799034edb0fb011716144 (patch)
treef5615c61acf5910b289511166f9a0cdf78b43e3e /net
parent4aa5dcb3891ffca0b09c3dd45328dc2b77194069 (diff)
downloadlinux-997cf2d8c206941b501799034edb0fb011716144.tar.gz
linux-997cf2d8c206941b501799034edb0fb011716144.tar.bz2
linux-997cf2d8c206941b501799034edb0fb011716144.zip
bpf: Check negative offsets in __bpf_skb_min_len()
[ Upstream commit 9ecc4d858b92c1bb0673ad9c327298e600c55659 ] skb_network_offset() and skb_transport_offset() can be negative when they are called after we pull the transport header, for example, when we use eBPF sockmap at the point of ->sk_data_ready(). __bpf_skb_min_len() uses an unsigned int to get these offsets, this leads to a very large number which then causes bpf_skb_change_tail() failed unexpectedly. Fix this by using a signed int to get these offsets and ensure the minimum is at least zero. Fixes: 5293efe62df8 ("bpf: add bpf_skb_change_tail helper") Signed-off-by: Cong Wang <cong.wang@bytedance.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: John Fastabend <john.fastabend@gmail.com> Link: https://lore.kernel.org/bpf/20241213034057.246437-2-xiyou.wangcong@gmail.com Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'net')
-rw-r--r--net/core/filter.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/net/core/filter.c b/net/core/filter.c
index 9a459213d283..55495063621d 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -3751,13 +3751,22 @@ static const struct bpf_func_proto bpf_skb_adjust_room_proto = {
static u32 __bpf_skb_min_len(const struct sk_buff *skb)
{
- u32 min_len = skb_network_offset(skb);
+ int offset = skb_network_offset(skb);
+ u32 min_len = 0;
- if (skb_transport_header_was_set(skb))
- min_len = skb_transport_offset(skb);
- if (skb->ip_summed == CHECKSUM_PARTIAL)
- min_len = skb_checksum_start_offset(skb) +
- skb->csum_offset + sizeof(__sum16);
+ if (offset > 0)
+ min_len = offset;
+ if (skb_transport_header_was_set(skb)) {
+ offset = skb_transport_offset(skb);
+ if (offset > 0)
+ min_len = offset;
+ }
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ offset = skb_checksum_start_offset(skb) +
+ skb->csum_offset + sizeof(__sum16);
+ if (offset > 0)
+ min_len = offset;
+ }
return min_len;
}