bpf_prog_test_run_skb() derives skb->protocol from the Ethernet header through eth_type_trans(), but it does not verify that the provided linear input is long enough to contain the corresponding L3 base header. This can construct an inconsistent skb for test_run: the packet can be recognized as IPv6 while skb_headlen() still only covers ETH_HLEN bytes. In that case, helpers such as bpf_skb_adjust_room() may compute offsets based on the inferred protocol and operate on bytes beyond the initialized linear data, which can trigger KMSAN. Reject such malformed IPv4/IPv6 skb test input early by checking that the linear head covers both the Ethernet header and the corresponding IPv4/IPv6 base header before running the program. Reported-by: syzbot+619b9ef527f510a57cfc@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=619b9ef527f510a57cfc Signed-off-by: Sun Jian --- net/bpf/test_run.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c index 178c4738e63b..65cfb408f52b 100644 --- a/net/bpf/test_run.c +++ b/net/bpf/test_run.c @@ -1118,6 +1118,25 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr, skb->protocol = eth_type_trans(skb, dev); skb_reset_network_header(skb); + switch (skb->protocol) { + case htons(ETH_P_IP): + if (skb_headlen(skb) < ETH_HLEN + sizeof(struct iphdr)) { + ret = -EINVAL; + goto out; + } + break; +#if IS_ENABLED(CONFIG_IPV6) + case htons(ETH_P_IPV6): + if (skb_headlen(skb) < ETH_HLEN + sizeof(struct ipv6hdr)) { + ret = -EINVAL; + goto out; + } + break; +#endif + default: + break; + } + switch (skb->protocol) { case htons(ETH_P_IP): sk->sk_family = AF_INET; base-commit: cbfffcca2bf0622b601b7eaf477aa29035169184 -- 2.43.0