From 7076f684d5132e6a6145e1da2fa74771ecd052e5 Mon Sep 17 00:00:00 2001 From: Dudu Lu Date: Wed, 21 Oct 2026 23:54:01 +0800 Subject: [PATCH] net/sched: etf: initialise the sock_exterr_skb before filling it report_sock_error() clones the transmitted skb, overlays a struct sock_exterr_skb on its control block and fills in the seven struct sock_extended_err fields, but never clears addr_offset and port. skb_clone() copies cb[] verbatim, so the errqueue entry carries the TX skb's stale control block to the receive side, and the ipv4 error-queue reader trusts those bytes: net/ipv4/ip_sockglue.c:556 sin->sin_addr.s_addr = *(__be32 *)(skb_network_header(skb) + serr->addr_offset); sin->sin_port = serr->port; The gate that is supposed to guard that read only asks whether an address was requested at all: net/ipv4/ip_sockglue.c:484 return serr->ee.ee_origin == SO_EE_ORIGIN_ICMP || serr->ee.ee_origin == SO_EE_ORIGIN_LOCAL || serr->port; SO_EE_ORIGIN_TXTIME is neither ICMP nor LOCAL, so for sch_etf the gate is decided by serr->port alone -- by the stale byte pair. When it is non-zero the reader dereferences skb_network_header() + addr_offset with an arbitrary offset. On the TCP path cb[40..44) is not zero: the transmit path stored delivered_mstamp there (tcp_rate_skb_sent()), which is exactly where addr_offset/port sit in the arm64 struct layout. Reached with an unmodified 7.3-rc4 (arm64, KASAN, in-tree modules): a TCP socket enables TX-timestamp error reporting (SO_TXTIME with SOF_TXTIME_REPORT_ERRORS), a sch_etf qdisc drops the packet, and a recvmsg() reaches ip_recv_error(): BUG: KASAN: slab-out-of-bounds in ip_recv_error+0x970/0xa0c Read of size 4 at addr ffff0000158ffdd5 by task A-227-A227-1_S2/113 ip_recv_error+0x970/0xa0c inet_recv_error+0x94/0xdc tcp_recvmsg+0x378/0x408 ... The buggy address is located 149 bytes to the right of allocated 704-byte region Zero the whole overlay rather than the two fields individually: the errqueue entry is handed to the receive side as a self-contained record, which is what every other producer in the tree already does (sch_etf was the only error-queue producer that cleared neither field). This does not change what the in-tree selftest observes -- so_txtime.c reads only ee_origin/ee_errno/ee_code/ee_data/ee_info, never msg_name or sin_port. Fixes: 4b15c7075352 ("net/sched: Make etf report drops on error_queue") Signed-off-by: Dudu Lu Reviewed-by: Simon Horman Link: https://patch.msgid.link/20261021155401.65997-1-phx0fer@gmail.com Signed-off-by: Jakub Kicinski --- net/sched/sch_etf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/sched/sch_etf.c b/net/sched/sch_etf.c index ada87a81da6a..aaafcf640bc7 100644 --- a/net/sched/sch_etf.c +++ b/net/sched/sch_etf.c @@ -147,6 +147,7 @@ static void report_sock_error(struct sk_buff *skb, u32 err, u8 code) return; serr = SKB_EXT_ERR(clone); + memset(serr, 0, sizeof(*serr)); serr->ee.ee_errno = err; serr->ee.ee_origin = SO_EE_ORIGIN_TXTIME; serr->ee.ee_type = 0;