From 47b393b997aee31942114ef1d793f2ae6d72b766 Mon Sep 17 00:00:00 2001 From: Anton Danilov Date: Wed, 14 Oct 2026 08:46:15 +0300 Subject: [PATCH] tun: use pskb_may_pull_reason() and remove SKB_DROP_REASON_HDR_TRUNC tun_get_user() is the only user of SKB_DROP_REASON_HDR_TRUNC. It sets it when pskb_may_pull() fails to pull the Ethernet header of a frame written to a TAP device. pskb_may_pull_reason() reports why the pull failed: PKT_TOO_SMALL if the packet is shorter than requested, NOMEM if pulling the data into the linear area fails. Use it for both header pulls in tun_get_user(), on TAP and on TUN devices, and remove the now unused SKB_DROP_REASON_HDR_TRUNC. The pull of the IP version byte on a TUN device with IFF_NO_PI was reported as NOT_SPECIFIED and now reports PKT_TOO_SMALL, for example when only the virtio-net header is written. After a successful pull drop_reason is SKB_NOT_DROPPED_YET. The later error paths without a reason of their own, the unknown IP version on TUN, the virtio-net header conversion and the path that finds the queue detached, relied on the SKB_DROP_REASON_NOT_SPECIFIED initializer. Fall back to SKB_DROP_REASON_NOT_SPECIFIED at the free_skb label, as vxlan_rcv() does, so that these paths, and any later one without a reason of its own, keep reporting it. The errors returned to user space do not change. Suggested-by: Ido Schimmel Link: https://lore.kernel.org/netdev/20260923145931.GA2859441@shredder/ Assisted-by: LLM Signed-off-by: Anton Danilov Reviewed-by: Willem de Bruijn Reviewed-by: Ido Schimmel Link: https://patch.msgid.link/20261014054615.1656074-1-littlesmilingcloud@gmail.com Signed-off-by: Paolo Abeni --- drivers/net/tun.c | 8 +++++--- include/net/dropreason-core.h | 7 ------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 8b82a7fe6ec7..d4152c9ba8df 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1903,7 +1903,8 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, if (tun->flags & IFF_NO_PI) { u8 ip_version; - if (!pskb_may_pull(skb, 1)) { + drop_reason = pskb_may_pull_reason(skb, 1); + if (drop_reason) { err = -EINVAL; goto drop; } @@ -1926,9 +1927,9 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, skb->protocol = pi.proto; break; case IFF_TAP: - if (!pskb_may_pull(skb, ETH_HLEN)) { + drop_reason = pskb_may_pull_reason(skb, ETH_HLEN); + if (drop_reason) { err = -ENOMEM; - drop_reason = SKB_DROP_REASON_HDR_TRUNC; goto drop; } skb_set_network_header(skb, ETH_HLEN); @@ -2065,6 +2066,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, dev_core_stats_rx_dropped_inc(tun->dev); free_skb: + drop_reason = drop_reason ?: SKB_DROP_REASON_NOT_SPECIFIED; if (!IS_ERR_OR_NULL(skb)) kfree_skb_reason(skb, drop_reason); diff --git a/include/net/dropreason-core.h b/include/net/dropreason-core.h index 664249924219..fa2fe8990557 100644 --- a/include/net/dropreason-core.h +++ b/include/net/dropreason-core.h @@ -82,7 +82,6 @@ FN(DEV_READY) \ FN(FULL_RING) \ FN(NOMEM) \ - FN(HDR_TRUNC) \ FN(TAP_FILTER) \ FN(TAP_TXFILTER) \ FN(ICMP_CSUM) \ @@ -427,12 +426,6 @@ enum skb_drop_reason { SKB_DROP_REASON_FULL_RING, /** @SKB_DROP_REASON_NOMEM: error due to OOM */ SKB_DROP_REASON_NOMEM, - /** - * @SKB_DROP_REASON_HDR_TRUNC: failed to trunc/extract the header from - * networking data, e.g., failed to pull the protocol header from - * frags via pskb_may_pull() - */ - SKB_DROP_REASON_HDR_TRUNC, /** * @SKB_DROP_REASON_TAP_FILTER: dropped by (ebpf) filter directly attached * to tun/tap, e.g., via TUNSETFILTEREBPF