Re: [PATCH net v2] netrom: fix out-of-bounds read in nr_rx_frame()
From: Disclosure <hidden>
Date: 2025-09-03 18:25:17
Hi Eric, Thanks a lot for the suggestions -- that's way better. I’ve sent v3, which follows your plan to linearize and add per-context length checks: https://lore.kernel.org/all/20250903181915.6359-1-disclosure@aisle.com/T/#u (local) - Use skb_linearize() at the start of nr_rx_frame(). - Require skb->len >= NR_NETWORK_LEN + NR_TRANSPORT_LEN before reading base fields (offsets 0-19). - Existing-socket path: for NR_CONNACK, require one extra byte for the window (>=21). Keep the BPQ ext detection for len == 22. - CONNREQ path: require window + user address present (>= 28) before reading offsets 20-27. Keep the optional timeout only when len == 37. - IP-over-NET/ROM path unchanged. This should avoid both OOB reads and potential UAF from earlier unvalidated accesses, and it answers the minimal length concern by checking the exact lengths needed at each access point. Please let me know if this is good enough or if anything else should be changed or improved. Thanks a lot! Best wishes, Stanislav Fort Aisle Research On Tuesday, September 2, 2025 at 3:17:14 PM UTC+3 Eric Dumazet wrote:
On Tue, Sep 2, 2025 at 4:27 AM Stanislav Fort [off-list ref] wrote:quoted
Add early pskb_may_pull() validation in nr_rx_frame() to prevent out-of-bounds reads when processing malformed NET/ROM frames. The vulnerability occurs when nr_route_frame() accepts frames as short as NR_NETWORK_LEN (15 bytes) but nr_rx_frame() immediately accesses the 5-byte transport header at bytes 15-19 without validation. For CONNREQ frames, additional fields are accessed (window at byte 20, user address at bytes 21-27, optional BPQ timeout at bytes 35-36). Attack vector: External AX.25 I-frames with PID=0xCF (NET/ROM) can reach nr_route_frame() via the AX.25 protocol dispatch mechanism: ax25_rcv() -> ax25_rx_iframe() -> ax25_protocol_function(0xCF) -> nr_route_frame() For frames destined to local NET/ROM devices, nr_route_frame() calls nr_rx_frame() which immediately dereferences unvalidated offsets, causing out-of-bounds reads that can crash the kernel or leak memory. Fix by using pskb_may_pull() early to linearize the maximum required packet size (37 bytes) before any pointer assignments. This prevents use-after-free issues when pskb_may_pull() reallocates skb->head and ensures all subsequent accesses are within bounds. Reported-by: Stanislav Fort <redacted> Signed-off-by: Stanislav Fort <redacted> --- net/netrom/af_netrom.c | 4 ++++ 1 file changed, 4 insertions(+)diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 3331669d8e33..3056229dcd20 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c@@ -883,7 +883,11 @@ int nr_rx_frame(struct sk_buff *skb, structnet_device *dev)quoted
/* * skb->data points to the netrom frame start + * Linearize the packet early to avoid use-after-free issues + * when pskb_may_pull() reallocates skb->head later */ + if (!pskb_may_pull(skb, max(NR_NETWORK_LEN + NR_TRANSPORT_LEN + 1 +AX25_ADDR_LEN, 37)))quoted
+ return 0;I am not sure about the minimal packet length we expect from this point. I was suggesting to use skb_linearize() here, but then add the needed skb->len checks of various sizes depending on the context (different places you had patched earlier) Thank you.