From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f171.google.com (mail-pl1-f171.google.com [209.85.214.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EE47031987D for ; Tue, 16 Jun 2026 07:34:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.171 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781595298; cv=none; b=ICtJTuHWNsdO1b3HDARuH87WCYkEi3xBdgnw3pQcp58vHkNl+jOjq3xlAU0E9wdqWb9NVfGEbRBsWvps6un9bx08W1oYIYL5iHtWrPwueBWPqeuHjp7DQZjXbnfDfTY+Bof6XnUegccy9gVuHB3Dc/TrdOxVYsor9vV9k4pUyJc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781595298; c=relaxed/simple; bh=Rog+vecIJCOoaRBhO4RUtb8aiERuWh4RE6w1j+WTzCo=; h=From:To:Cc:Subject:Date:Message-ID:Content-Type:MIME-Version; b=pqUMPeC6ggmnT7FOWH7DMiB2luDeM/ePMONj4OCwDNK6yK4ZQQrfD2YzFJuLs4KuPLIx02oki8TjWIbox16UyCJSj9w+8X1zJTHrM4jp9uJyFvOHTzHGPMOnm30mrECTZKkM59MLZATmDq5YrDumktCir9IOQhZ1gY0MFwNHdTI= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=VwV073eR; arc=none smtp.client-ip=209.85.214.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="VwV073eR" Received: by mail-pl1-f171.google.com with SMTP id d9443c01a7336-2c0bb4a94b8so32991225ad.2 for ; Tue, 16 Jun 2026 00:34:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1781595296; x=1782200096; darn=vger.kernel.org; h=mime-version:content-transfer-encoding:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=je9fX3o0/RPXSuKvoC8V4ThqHHI+ZMgmBm1tthpZ5bQ=; b=VwV073eR7f+ulqH91jtVi3JUTQjw3PjCx4qcWZ6JpEibCsRnqFRLHrvSFMiZPSSdR3 OV2vWB+w2kWoBRowkss2TFgBwN4Ms73enrZ0f0W17Bj0JNRTL/XgbaIipbKLJqr6+0bg KJ4Uyt/7AgR8gz+QU/pZrce1iaQT7ZIfeajV+xKG7EsfrwBaV/g5z01QqClku57BRKre wmTRDNDn1rBdB4vep/ntoNiG5Ti29RUu6KYf/c9537J5TFuQ0zOJC5Ligr4NIIbshbdy 55HKN1PnG/ekz8Ltgs4CfbuAoYBFw5v95HqlvmG6taIaaLmz9Sj15GE4CNVGF0kbD1a9 lu1Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781595296; x=1782200096; h=mime-version:content-transfer-encoding:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=je9fX3o0/RPXSuKvoC8V4ThqHHI+ZMgmBm1tthpZ5bQ=; b=PtOiClNNOb6gKg9VWSiH07m/jR9H5fIyFHOgIuaKkx5ZgSyHUM9zEHyazxGeIhGhGf 2FzsdPhBN96WvKDtp9x2jzLPcFbHPlt8YYHJJha//PaOvnD+9UjuH1K4ELEKn6HLmN48 HDOu6BCt+JJ/Cux3JtWJ33HbEfYocPUOFNOKbV0XJ5xoV1ottaqC+dTNhKeA82p+YEXh MpY15hhZezsd57xAA8vVvEErMTz6WDs25NcUgpsGmms4pnxweVag6aukZQd3Ct8Wu4WH JnTX1Ar/fwbFDe6WizVcG+d18U17GFr7+KgTNdwZfZsXlKdjgJBF/2tsc1YY+XhsIz6P aiUg== X-Forwarded-Encrypted: i=1; AFNElJ/GTgHmmopymEqbhTDI25Xy5B0Mia4OZ+1ZrC36495ZzwpZO0fLHeRa0Ap3nxzaEdMBA176vH0a4AR03WE=@vger.kernel.org X-Gm-Message-State: AOJu0YzaNgYJpfnIpkhc1+umCOukIJcEtP9sRfxc0EITIUI+ohnNPR2E +earW8629lANW5HoRHd7w0cyNjhYAUQXZXMSAidvm4cLMvqgEiY2z4ls X-Gm-Gg: Acq92OE+yoK9ApQciWoRjhfV4KYa+3Pi2EObgcyJSW+RB1+rYhZxr0qQ0iN0RfGdqNj SDLLDkpbOMdjOIt5eitHNl4g7Bm4A1h1KZ5p2JOnDhAGYeH2d1QtTlpnFGzZJ7A9wMLSymX5G5K XgJiopj7LcwnOZgwOpyx/3J1MocXr1pSgc1JNFAtcAu6Z22a/gCSLF4UJy/XAU3l6zbGroTni4V ZmBNs/8H8cop0z36Rf9KNWmpWxEW1Xf1SlymAT9lcHo+EQTtpLGAGcGQAe59dYDsxyb1SdLN04g LrNfyybVuVeHG4DWoyVMCDKnhLcL3TGIlx+8tctg55oif/hfOPJ9wm7gjwZm4T6pNPGd+VjO3mW FxrNCCV1J3rLBqENNbZ5m+WlHd5082ldGCoj+qZ/bESUA+lxuuF7V4rb5D3LLGlq0c/Rs6TBeJq +uF215lfBKnWWPGUpIVhEplGO/bB3v61S40z3B6AGSJzMFYGpa X-Received: by 2002:a17:903:3887:b0:2b2:4d36:7ba with SMTP id d9443c01a7336-2c40e0350d2mr192684905ad.0.1781595296273; Tue, 16 Jun 2026 00:34:56 -0700 (PDT) Received: from csl-conti-dell7858.ntu.edu.sg ([155.69.195.57]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2c6a3ee1052sm4186635ad.48.2026.06.16.00.34.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 16 Jun 2026 00:34:55 -0700 (PDT) From: Maoyi Xie To: Mika Westerberg , Yehezkel Bernat Cc: Andrew Lunn , Jakub Kicinski , Paolo Abeni , netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: net: thunderbolt: tbnet_poll() can overflow skb_shinfo()->frags[] Date: Tue, 16 Jun 2026 15:34:52 +0800 Message-ID: <178159529251.2170936.1136950368069628844@maoyixie.com> Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Hi all, After the recent skb frags[] overflow fixes (t7xx, cdc-phonet, f_phonet), I went looking for the same pattern. I think tbnet_poll() in drivers/net/thunderbolt/main.c has it too. I would appreciate it if you could take a look. tbnet_poll() reassembles a ThunderboltIP packet that spans several frames into one skb. It adds one rx fragment per frame. skb =3D net->skb; if (!skb) { skb =3D build_skb(...); ... net->skb =3D skb; } else { skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, hdr_size, frame_size, TBNET_RX_PAGE_SIZE - hdr_size); } Nothing checks skb_shinfo(skb)->nr_frags against MAX_SKB_FRAGS here. The frame count comes from the peer, in the frame header. tbnet_check_frame() only boun= ds it at the start of a packet. if (frame_count =3D=3D 0 || frame_count > TBNET_RING_SIZE / 4) { net->stats.rx_length_errors++; return false; } TBNET_RING_SIZE is 256, so frame_count can be as large as 64. MAX_SKB_FRAGS i= s 17 by default. Frame 0 builds the skb and every frame after it adds a fragment, = so nr_frags can reach 63. Once nr_frags hits MAX_SKB_FRAGS, skb_add_rx_frag() wr= ites one entry past skb_shinfo()->frags[]. The frame_size and MTU checks do not st= op this. With small frames, 64 fragments stay well under TBNET_MAX_MTU. So a malicious or buggy peer can send a packet with frame_count between 19 and 64. The frames only need to increment the way tbnet_check_frame() wants. That drives nr_frags past frags[] and overruns skb_shared_info. The fix I had in mind mirrors f0813bcd2d9d ("net: wwan: t7xx: fix potential skb->frags overflow in RX path") and 600dc40554dc ("net: usb: cdc-phonet: fix skb frags[] overflow in rx_complete()"). Add the fragment only while there is room, and drop the packet otherwise. - } else { + } else if (skb_shinfo(skb)->nr_frags < MAX_SKB_FRAGS) { skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, hdr_size, frame_size, TBNET_RX_PAGE_SIZE - hdr_size); + } else { + net->stats.rx_length_errors++; + __free_pages(page, TBNET_RX_PAGE_ORDER); + dev_kfree_skb_any(net->skb); + net->skb =3D NULL; + continue; } I do not have two Thunderbolt hosts, so this is from reading the code. I can = put together a focused reproducer if that helps. Does this look like a real overflow? And is the MAX_SKB_FRAGS guard the right place, or would you rather tighten the frame_count bound in tbnet_check_frame= ()? It has been there since the driver was added (e69b6c02b4c3), so it is a stable candidate. Happy to send a proper patch once you confirm. Thanks, Maoyi https://maoyixie.com/