From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8799257ED82; Mon, 31 Aug 2026 13:49:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788184182; cv=none; b=Q7RRtl14urPCYYaYrDpMsvQpEg+CoZppclTBPMpO34vesSUA/0YPAtABnDrOb9Vqlz/wk5sQaQof5h5mv81GtmVVC+WmJ87PORDMsjW0oRJZ4CSu1rMJ3+tEgIL6wn/cu+aJXH3WCs4d0BgJd72eZDokC5j3TQvkrVKQPpf++nk= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788184182; c=relaxed/simple; bh=tE3HKNPGw+9rGa08tYZziWaTsPe4o8mNZUeAYnZY35w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=q98r4NRsEZLFKpIfcHqnlMeSzhgr9grcuiqqUt4MoV6El/N0e+LmYDXZ7C1bn3QQjr2Ye06LUkZjkfxlz/U+qORLYlOoyH866QhLb2i29kuiC7IofGHHkirQn9Cw5ftb5L5R+bT7i5BwZ2BXqeNL8vS3A55XrcJ2l93LtYSLkps= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=f/aebtDw; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="f/aebtDw" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B40551F00ACA; Mon, 31 Aug 2026 13:49:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788184180; bh=9iH17oayUWeHt8Tfzh4cjBq2lKQGzJhvxTnN2dA1kUE=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=f/aebtDwdqqLE/MTKny02mW+GiKK7NiNyYaKuRlhh727C6DsNdyIW+5BcW3nLCxP+ AwqWyUjME+y2mmPi3XH3derl6EgUaDjjxuCDRGx0fl5UWjMH19307lfc3JwpYipEp/ PMis1uYaBDFiz4QJ0B3b+9GULOkwl9UOocNWmT453LTKnSIJuhhTAebhdVhh0kITbE i98HPzxp9GOQnle9O9c5xXsD9UT5TozeWU6OC63MfmvfcKoF9ggfg8Ray3NyttYHNx QEXzysoIqhn03y/x1SKV4xIB2Ry4P0fP0Zy9PwUwE4tFr6B7x59OTlETm9TuzWzDY9 /TyUsobaTaS3A== From: Sasha Levin To: patches@lists.linux.dev, stable@vger.kernel.org Cc: Sechang Lim , Jiayuan Chen , Alexei Starovoitov , Sasha Levin , john.fastabend@gmail.com, jakub@cloudflare.com, edumazet@google.com, kuniyu@google.com, pabeni@redhat.com, willemb@google.com, davem@davemloft.net, kuba@kernel.org, netdev@vger.kernel.org, bpf@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH AUTOSEL 6.18] bpf, sockmap: reject a packet-modifying SK_SKB stream parser Date: Mon, 31 Aug 2026 09:29:27 -0400 Message-ID: <20260831133314.4125787-539-sashal@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260831133314.4125787-1-sashal@kernel.org> References: <20260831133314.4125787-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore X-stable-base: Linux 6.18.48 Content-Transfer-Encoding: 8bit From: Sechang Lim [ Upstream commit 31e2f36d3821811c03bddf5fd99ed8fc884fd222 ] sk_psock_strp_parse() runs the BPF_PROG_TYPE_SK_SKB stream-parser program to find the length of the next message. strparser assembles a message out of several received skbs by chaining them onto the head's frag_list and recording where to append the next one in strp->skb_nextp: *strp->skb_nextp = skb; strp->skb_nextp = &skb->next; and then calls the parser on the head: len = (*strp->cb.parse_msg)(strp, head); The parser is only meant to inspect the skb, but the program may call bpf_skb_change_tail() -- or the sibling bpf_skb_pull_data(), bpf_skb_change_head(), bpf_skb_adjust_room(), all allowed for SK_SKB. Once the head carries a frag_list these go ... -> skb_ensure_writable -> pskb_may_pull -> __pskb_pull_tail and __pskb_pull_tail() frees the frag_list skbs that strparser still tracks through skb_nextp: while ((list = skb_shinfo(skb)->frag_list) != insp) { skb_shinfo(skb)->frag_list = list->next; consume_skb(list); } strp->skb_nextp now points into a freed sk_buff. The next segment of the same message arrives in __strp_recv(), which links it with *strp->skb_nextp = skb, an 8-byte write into the freed skb. The free and the write happen in different __strp_recv() calls, so the message has to span at least three segments before it triggers. BUG: KASAN: slab-use-after-free in __strp_recv+0x447/0xda0 Write of size 8 at addr ffff88810db86140 by task repro/349 Call Trace: __strp_recv+0x447/0xda0 __tcp_read_sock+0x13d/0x590 tcp_bpf_strp_read_sock+0x195/0x320 strp_data_ready+0x267/0x340 sk_psock_strp_data_ready+0x1ce/0x350 tcp_data_queue+0x1364/0x2fd0 tcp_rcv_established+0xe07/0x1640 [...] Allocated by task 349: skb_clone+0x17b/0x210 __strp_recv+0x2c3/0xda0 __tcp_read_sock+0x13d/0x590 [...] Freed by task 349: kmem_cache_free+0x150/0x570 __pskb_pull_tail+0x57b/0xc20 skb_ensure_writable+0x236/0x260 __bpf_skb_change_tail+0x1d4/0x590 sk_skb_change_tail+0x2a/0x40 bpf_prog_1b285dcd6c41373e+0x27/0x30 bpf_prog_run_pin_on_cpu+0xf3/0x260 sk_psock_strp_parse+0x118/0x1e0 __strp_recv+0x4f6/0xda0 [...] The same resize also leaves the head's length inconsistent with its frags, so a later __pskb_pull_tail() can instead hit the BUG_ON(skb_copy_bits(...)) in net/core/skbuff.c. A stream parser is only meant to measure the next message, not to modify the packet. Reject a parser whose program can change packet data (prog->aux->changes_pkt_data) at attach time. The check is shared by sock_map_prog_update() and sock_map_link_update_prog(), which between them cover prog attach, link create and link update. Verdict programs are unaffected and may still modify the skb. Reviewed-by: Jiayuan Chen Signed-off-by: Sechang Lim Link: https://lore.kernel.org/r/20260620024423.4141004-3-rhkrqnwk98@gmail.com Signed-off-by: Alexei Starovoitov Signed-off-by: Sasha Levin --- LLM Generated explanations, may be completely bogus: The verification command finished: neither `git log --grep='packet- modifying'` nor a search for `sock_map_prog_attach_check` returned any commits. That confirms the fix is not in the **6.18.44** tree, which aligns with the **YES** backport recommendation. net/core/sock_map.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/net/core/sock_map.c b/net/core/sock_map.c index 70bbc78fb079f..4ecc6cc6491fd 100644 --- a/net/core/sock_map.c +++ b/net/core/sock_map.c @@ -1517,6 +1517,17 @@ static int sock_map_prog_link_lookup(struct bpf_map *map, struct bpf_prog ***ppr return 0; } +static int sock_map_prog_attach_check(enum bpf_attach_type attach_type, + struct bpf_prog *prog) +{ + /* A stream parser must not modify the skb, only measure it. */ + if (prog && attach_type == BPF_SK_SKB_STREAM_PARSER && + prog->aux->changes_pkt_data) + return -EINVAL; + + return 0; +} + /* Handle the following four cases: * prog_attach: prog != NULL, old == NULL, link == NULL * prog_detach: prog == NULL, old != NULL, link == NULL @@ -1535,6 +1546,10 @@ static int sock_map_prog_update(struct bpf_map *map, struct bpf_prog *prog, if (ret) return ret; + ret = sock_map_prog_attach_check(which, prog); + if (ret) + return ret; + /* for prog_attach/prog_detach/link_attach, return error if a bpf_link * exists for that prog. */ @@ -1767,6 +1782,11 @@ static int sock_map_link_update_prog(struct bpf_link *link, ret = -EINVAL; goto out; } + + ret = sock_map_prog_attach_check(link->attach_type, prog); + if (ret) + goto out; + if (!sockmap_link->map) { ret = -ENOLINK; goto out; -- 2.53.0