From 0c03a83d9853b1d7f88a7399a8d08b35696f78a5 Mon Sep 17 00:00:00 2001 From: Stanislav Fort Date: Mon, 25 Aug 2025 19:51:12 +0200 Subject: [PATCH] [PATCH net] netrom: validate header lengths in nr_rx_frame() using pskb_may_pull() NET/ROM nr_rx_frame() dereferences the 5-byte transport header unconditionally. nr_route_frame() currently accepts frames as short as NR_NETWORK_LEN (15 bytes), which can lead to small out-of-bounds reads on short frames. Fix by using pskb_may_pull() in nr_rx_frame() to ensure the full NET/ROM network + transport header is present before accessing it, and guard the extra fields used by NR_CONNREQ (window, user address, and the optional BPQ timeout extension) with additional pskb_may_pull() checks. This aligns with recent fixes using pskb_may_pull() to validate header availability. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Reported-by: Stanislav Fort Cc: stable@vger.kernel.org Signed-off-by: Stanislav Fort --- net/netrom/af_netrom.c | 12 +++++++++++- net/netrom/nr_route.c | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 3331669d8e33..1fbaa161288a 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -885,6 +885,10 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev) * skb->data points to the netrom frame start */ + /* Ensure NET/ROM network + transport header are present */ + if (!pskb_may_pull(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN)) + return 0; + src = (ax25_address *)(skb->data + 0); dest = (ax25_address *)(skb->data + 7); @@ -961,6 +965,12 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev) return 0; } + /* Ensure NR_CONNREQ fields (window + user address) are present */ + if (!pskb_may_pull(skb, 21 + AX25_ADDR_LEN)) { + nr_transmit_refusal(skb, 0); + return 0; + } + sk = nr_find_listener(dest); user = (ax25_address *)(skb->data + 21); @@ -1005,7 +1015,7 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev) nr_make->window = window; /* L4 timeout negotiation */ - if (skb->len == 37) { + if (skb->len == 37 && pskb_may_pull(skb, 37)) { timeout = skb->data[36] * 256 + skb->data[35]; if (timeout * HZ < nr_make->t1) nr_make->t1 = timeout * HZ; diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c index b94cb2ffbaf8..b4b0ee546799 100644 --- a/net/netrom/nr_route.c +++ b/net/netrom/nr_route.c @@ -758,7 +758,7 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25) * Reject malformed packets early. Check that it contains at least 2 * addresses and 1 byte more for Time-To-Live */ - if (skb->len < 2 * sizeof(ax25_address) + 1) + if (skb->len < NR_NETWORK_LEN) return 0; nr_src = (ax25_address *)(skb->data + 0); -- 2.39.3 (Apple Git-146)