From: Mohsin Bashir <mohsin.bashr@gmail.com>
To: Yehyeong Lee <yhlee@isslab.korea.ac.kr>,
Alexander Duyck <alexanderduyck@fb.com>,
Jakub Kicinski <kuba@kernel.org>,
netdev@vger.kernel.org
Cc: kernel-team@meta.com, Andrew Lunn <andrew+netdev@lunn.ch>,
davem@davemloft.net, Eric Dumazet <edumazet@kernel.org>,
Paolo Abeni <pabeni@redhat.com>, Simon Horman <horms@kernel.org>,
Dimitri Daskalakis <daskald@meta.com>,
Bobby Eshleman <bobbyeshleman@meta.com>,
Daniel Zahka <daniel.zahka@gmail.com>,
stable@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH net v3 2/5] eth: fbnic: validate the Rx completion offset and length
Date: Mon, 12 Oct 2026 01:22:07 -0700 [thread overview]
Message-ID: <36768a07-1dfd-4a80-9aa0-423a324b5839@gmail.com> (raw)
In-Reply-To: <5b7c2618b56d35f50b6847d565a0050cf2a7f371.1791775409.git.yhlee@isslab.korea.ac.kr>
On 10/11/26 9:15 PM, Yehyeong Lee wrote:
> fbnic_pkt_prepare() and fbnic_add_rx_frag() take the offset and length
> from the completion descriptor (FBNIC_RCD_AL_BUFF_OFF_MASK and _LEN_MASK)
> and use them to place data in the fragment page without checking them. A
> device that reports an offset below the reserved headroom, or a length
> that runs past the 4K fragment, produces a negative headroom and a frame
> that extends beyond the page, which is then read out past the page into
> adjacent memory.
>
> Reject a header whose offset is below FBNIC_RX_HROOM or whose offset plus
> length exceeds the fragment, and a payload whose offset plus length
> exceeds the fragment, via the drop path. Clamp the derived frame end and
> truesize to the fragment so a FIN descriptor cannot push them past the
> page. A maximum-size header (offset 192, length 3584) stays inside the
> fragment and is still accepted.
>
> BUG: unable to handle page fault for address: ffffed1021a8ee10
> #PF: supervisor read access in kernel mode
> #PF: error_code(0x0000) - not-present page
> Oops: Oops: 0000 [#1] SMP KASAN NOPTI
> RIP: 0010:kasan_check_range+0x15e/0x1b0
> Call Trace:
> <TASK>
> __asan_memset+0x23/0x50
> __build_skb_around+0x222/0x320
> napi_build_skb+0x50/0x1e0
> xdp_build_skb_from_buff+0xda/0x8b0
> fbnic_run_xdp+0x29a/0x1040 [fbnic]
>
> An offset and length that keep the frame inside the page but past the
> valid data produce no splat: the read lands in adjacent page_pool memory,
> which carries no KASAN redzone, and is copied into the skb silently.
>
> Fixes: a29b8eb6e533 ("eth: fbnic: Add basic Rx handling")
> Cc: stable@vger.kernel.org
> Signed-off-by: Yehyeong Lee <yhlee@isslab.korea.ac.kr>
> ---
> drivers/net/ethernet/meta/fbnic/fbnic_txrx.c | 41 ++++++++++++++++++--
> 1 file changed, 38 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c
> index 305fe6d2f511f..7dda59bba14ee 100644
> --- a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c
> +++ b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c
> @@ -1037,13 +1037,34 @@ static void fbnic_pkt_prepare(struct fbnic_napi_vector *nv, u64 rcd,
> return;
> }
>
> - page = fbnic_page_pool_get_head(qt, hdr_pg_idx);
> + /* The completion describes one frame inside the one
> + * FBNIC_BD_FRAG_SIZE fragment it names. fbnic_hdr_pg_start() takes
> + * the headroom back out of the offset, so an offset below the
> + * headroom underflows it, and the frame data runs to
> + * hdr_pg_off + len, which has to stay inside the fragment.
> + */
> + if (unlikely(hdr_pg_off < FBNIC_RX_HROOM ||
> + hdr_pg_off + len > FBNIC_BD_FRAG_SIZE)) {
> + pkt->add_frag_failed = true;
> + return;
> + }
>
> /* Short-cut the end calculation if we know page is fully consumed */
> hdr_pg_end = FIELD_GET(FBNIC_RCD_AL_PAGE_FIN, rcd) ?
> FBNIC_BD_FRAG_SIZE : fbnic_hdr_pg_end(hdr_pg_off, len);
> hdr_pg_start = fbnic_hdr_pg_start(hdr_pg_off);
>
> + /* fbnic_hdr_pg_end() rounds the frame up to where the next header
> + * would start, which can be past the end of the fragment when this
> + * frame is the last one in it. napi_build_skb() puts the shared
> + * info at the end of the frame, so hold the frame inside the
> + * fragment, which is what the FBNIC_RCD_AL_PAGE_FIN case above
> + * already does.
> + */
> + hdr_pg_end = min(hdr_pg_end, FBNIC_BD_FRAG_SIZE);
> +
> + page = fbnic_page_pool_get_head(qt, hdr_pg_idx);
> +
> headroom = hdr_pg_off - hdr_pg_start + FBNIC_RX_PAD;
> frame_sz = hdr_pg_end - hdr_pg_start;
> xdp_init_buff(&pkt->buff, frame_sz, &qt->xdp_rxq);
> @@ -1091,11 +1112,25 @@ static void fbnic_add_rx_frag(struct fbnic_napi_vector *nv, u64 rcd,
> return;
> }
>
> - netmem = fbnic_page_pool_get_data(qt, pg_idx);
> -
> truesize = FIELD_GET(FBNIC_RCD_AL_PAGE_FIN, rcd) ?
> FBNIC_BD_FRAG_SIZE - pg_off : ALIGN(len, 128);
>
> + /* The data has to stay inside the FBNIC_BD_FRAG_SIZE fragment the
> + * completion names.
> + */
> + if (unlikely(pg_off + len > FBNIC_BD_FRAG_SIZE)) {
> + pkt->add_frag_failed = true;
> + return;
> + }
> +
> + /* ALIGN() can round the charged size past the end of the fragment
> + * when this is the last fragment in it, so hold it inside, which is
> + * what the FBNIC_RCD_AL_PAGE_FIN case above already does.
> + */
> + truesize = min(truesize, FBNIC_BD_FRAG_SIZE - pg_off);
> +
> + netmem = fbnic_page_pool_get_data(qt, pg_idx);
> +
> pg_off += (FBNIC_RCD_AL_BUFF_FRAG_MASK & rcd) *
> FBNIC_BD_FRAG_SIZE;
>
The offset field is 12 bits, but that alone does not bound offset +
length. The relevant guarantee comes from the device’s placement
behavior. The driver configures RX_HROOM, RX_TROOM, and the max header
length, and the receive path expects the device to honor those
constraints. This patch assumes that the device violates those
programmed placement constraints. I doubt this can happen on real
healthy HW.
next prev parent reply other threads:[~2026-10-12 8:22 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-12 4:15 [PATCH net v3 0/5] eth: fbnic: harden Rx and Tx completion handling Yehyeong Lee
2026-10-12 4:15 ` [PATCH net v3 1/5] eth: fbnic: only act on Rx completions naming a posted buffer Yehyeong Lee
2026-10-12 8:18 ` Mohsin Bashir
2026-10-12 8:42 ` Yehyeong Lee
2026-10-12 4:15 ` [PATCH net v3 2/5] eth: fbnic: validate the Rx completion offset and length Yehyeong Lee
2026-10-12 8:22 ` Mohsin Bashir [this message]
2026-10-12 4:15 ` [PATCH net v3 3/5] eth: fbnic: return a pending Rx packet before reusing its buffer Yehyeong Lee
2026-10-12 8:24 ` Mohsin Bashir
2026-10-12 4:15 ` [PATCH net v3 4/5] eth: fbnic: return the page reference taken for a dropped Rx fragment Yehyeong Lee
2026-10-12 8:27 ` Mohsin Bashir
2026-10-12 4:16 ` [PATCH net v3 5/5] eth: fbnic: bound the XDP Tx completion head to the ring Yehyeong Lee
2026-10-12 8:34 ` Mohsin Bashir
2026-10-12 4:20 ` [PATCH net v3 0/5] eth: fbnic: harden Rx and Tx completion handling netdev-bot+sinfo
-- strict thread matches above, loose matches on Subject: below --
2026-10-13 4:35 [PATCH net v3 2/5] eth: fbnic: validate the Rx completion offset and length netdev-bot+sashiko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=36768a07-1dfd-4a80-9aa0-423a324b5839@gmail.com \
--to=mohsin.bashr@gmail.com \
--cc=alexanderduyck@fb.com \
--cc=andrew+netdev@lunn.ch \
--cc=bobbyeshleman@meta.com \
--cc=daniel.zahka@gmail.com \
--cc=daskald@meta.com \
--cc=davem@davemloft.net \
--cc=edumazet@kernel.org \
--cc=horms@kernel.org \
--cc=kernel-team@meta.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=stable@vger.kernel.org \
--cc=yhlee@isslab.korea.ac.kr \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.