Skip to content

Commit 60cd311

Browse files
committed
tcp: add sanity checks to rx zerocopy
jira LE-2015 cve CVE-2024-26640 Rebuild_History Non-Buildable kernel-5.14.0-427.42.1.el9_4 commit-author Eric Dumazet <edumazet@google.com> commit 577e443 TCP rx zerocopy intent is to map pages initially allocated from NIC drivers, not pages owned by a fs. This patch adds to can_map_frag() these additional checks: - Page must not be a compound one. - page->mapping must be NULL. This fixes the panic reported by ZhangPeng. syzbot was able to loopback packets built with sendfile(), mapping pages owned by an ext4 file to TCP rx zerocopy. r3 = socket$inet_tcp(0x2, 0x1, 0x0) mmap(&(0x7f0000ff9000/0x4000)=nil, 0x4000, 0x0, 0x12, r3, 0x0) r4 = socket$inet_tcp(0x2, 0x1, 0x0) bind$inet(r4, &(0x7f0000000000)={0x2, 0x4e24, @Multicast1}, 0x10) connect$inet(r4, &(0x7f00000006c0)={0x2, 0x4e24, @empty}, 0x10) r5 = openat$dir(0xffffffffffffff9c, &(0x7f00000000c0)='./file0\x00', 0x181e42, 0x0) fallocate(r5, 0x0, 0x0, 0x85b8) sendfile(r4, r5, 0x0, 0x8ba0) getsockopt$inet_tcp_TCP_ZEROCOPY_RECEIVE(r4, 0x6, 0x23, &(0x7f00000001c0)={&(0x7f0000ffb000/0x3000)=nil, 0x3000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, &(0x7f0000000440)=0x40) r6 = openat$dir(0xffffffffffffff9c, &(0x7f00000000c0)='./file0\x00', 0x181e42, 0x0) Fixes: 93ab6cc ("tcp: implement mmap() for zero copy receive") Link: https://lore.kernel.org/netdev/5106a58e-04da-372a-b836-9d3d0bd2507b@huawei.com/T/ Reported-and-bisected-by: ZhangPeng <zhangpeng362@huawei.com> Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Arjun Roy <arjunroy@google.com> Cc: Matthew Wilcox <willy@infradead.org> Cc: linux-mm@vger.kernel.org Cc: Andrew Morton <akpm@linux-foundation.org> Cc: linux-fsdevel@vger.kernel.org Signed-off-by: David S. Miller <davem@davemloft.net> (cherry picked from commit 577e443) Signed-off-by: Jonathan Maple <jmaple@ciq.com>
1 parent e01a6ee commit 60cd311

File tree

1 file changed

+11
-1
lines changed

1 file changed

+11
-1
lines changed

net/ipv4/tcp.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1921,7 +1921,17 @@ static skb_frag_t *skb_advance_to_frag(struct sk_buff *skb, u32 offset_skb,
19211921

19221922
static bool can_map_frag(const skb_frag_t *frag)
19231923
{
1924-
return skb_frag_size(frag) == PAGE_SIZE && !skb_frag_off(frag);
1924+
struct page *page;
1925+
1926+
if (skb_frag_size(frag) != PAGE_SIZE || skb_frag_off(frag))
1927+
return false;
1928+
1929+
page = skb_frag_page(frag);
1930+
1931+
if (PageCompound(page) || page->mapping)
1932+
return false;
1933+
1934+
return true;
19251935
}
19261936

19271937
static int find_next_mappable_frag(const skb_frag_t *frag,

0 commit comments

Comments
 (0)