Re: [PATCH net-next v4 03/10] gre: make gre_parse_header() report a drop reason
From: Ido Schimmel <idosch@nvidia.com>
Date: 2026-09-23 15:00:07
Also in:
lkml
On Wed, Sep 23, 2026 at 01:15:00AM +0300, Anton Danilov wrote:
quoted hunk ↗ jump to hunk
diff --git a/net/ipv4/gre_demux.c b/net/ipv4/gre_demux.c index 96fd7dc6d82d..e117056525f0 100644 --- a/net/ipv4/gre_demux.c +++ b/net/ipv4/gre_demux.c@@ -56,28 +56,35 @@ int gre_del_protocol(const struct gre_protocol *proto, u8 version) } EXPORT_SYMBOL_GPL(gre_del_protocol); -/* Fills in tpi and returns header length to be pulled. +/* Fills in tpi, including the header length to be pulled in tpi->hdr_len, + * and returns SKB_NOT_DROPPED_YET, or the reason to drop the packet if the + * header is rejected. * Note that caller must use pskb_may_pull() before pulling GRE header. + * + * @icmp_err is set by the ICMP error handlers, which only get a part of + * the original packet: a checksum failure does not reject the header then, + * the checksum is still computed and the rest of the header is parsed. */ -int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, - bool *csum_err, __be16 proto, int nhs) +enum skb_drop_reason +gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, + bool icmp_err, __be16 proto, int nhs) { const struct gre_base_hdr *greh; __be32 *options; int hdr_len; if (unlikely(!pskb_may_pull(skb, nhs + sizeof(struct gre_base_hdr)))) - return -EINVAL; + return SKB_DROP_REASON_HDR_TRUNC;
Please use pskb_may_pull_reason() as is done throughout the kernel. AFAICT, there's only one user of HDR_TRUNC (in tun) and it should also be converted to pskb_may_pull_reason() so that we could remove HDR_TRUNC. Can you send a patch?
greh = (struct gre_base_hdr *)(skb->data + nhs); if (unlikely(greh->flags & (GRE_VERSION | GRE_ROUTING))) - return -EINVAL; + return SKB_DROP_REASON_GRE_INVALID_HDR;
[...]
static int gre_rcv(struct sk_buff *skb)
{
+ enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
const struct gre_protocol *proto;
u8 ver;
int ret;
- if (!pskb_may_pull(skb, 12))
+ reason = pskb_may_pull_reason(skb, 12);
+ if (reason)
goto drop;
ver = skb->data[1]&0x7f;
- if (ver >= GREPROTO_MAX)
+ if (ver >= GREPROTO_MAX) {
+ reason = SKB_DROP_REASON_UNHANDLED_PROTO;This should be TUNNEL_INVALID_HDR to be consistent with the hunk above.
quoted hunk ↗ jump to hunk
goto drop; + } rcu_read_lock(); proto = rcu_dereference(gre_proto[ver]);@@ -167,11 +177,11 @@ static int gre_rcv(struct sk_buff *skb) drop_nohandler: rcu_read_unlock(); dev_core_stats_rx_nohandler_inc(skb->dev); - kfree_skb(skb); + kfree_skb_reason(skb, SKB_DROP_REASON_UNHANDLED_PROTO);
This looks correct.
return NET_RX_DROP; drop: dev_core_stats_rx_dropped_inc(skb->dev); - kfree_skb(skb); + kfree_skb_reason(skb, reason); return NET_RX_DROP; }