From: sashiko-bot@kernel.org
To: "Daniel Zahka" <daniel.zahka@gmail.com>
Cc: bpf@vger.kernel.org
Subject: Re: [PATCH net-next v2 8/8] eth: mpnic: add basic Rx handling
Date: Sat, 26 Sep 2026 00:36:02 +0000 [thread overview]
Message-ID: <20260926003603.45E161F000FF@smtp.kernel.org> (raw)
In-Reply-To: <20260924-linux-mpnic-v2-8-4badc9b58b9e@gmail.com>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] net: mpnic: rx starvation in mpnic_poll due to sequential queue processing
- [Medium] net: mpnic: NULL pointer dereference on META descriptor without HDR
- [Medium] net: mpnic: NULL pointer dereference on PAY descriptor without HDR
--
commit a3920f68fea82b63522bdc2a1f1ed39c3a9d052a
Author: Daniel Zahka <daniel.zahka@gmail.com>
eth: mpnic: add basic Rx handling
A frame arrives as a run of completion descriptors: one header
address/length descriptor, one address/length descriptor per payload
page, and a metadata descriptor that closes the frame. The frame is
assembled in an xdp_buff as the descriptors come in and handed to the
stack when the metadata descriptor arrives.
[ ... ]
> diff --git a/drivers/net/ethernet/meta/mpnic/mpnic_txrx.c b/drivers/net/ethernet/meta/mpnic/mpnic_txrx.c
> index 389a9e5476c6e..edb07b7f334bd 100644
> --- a/drivers/net/ethernet/meta/mpnic/mpnic_txrx.c
> +++ b/drivers/net/ethernet/meta/mpnic/mpnic_txrx.c
[ ... ]
> +static void
> +mpnic_add_rx_frag(u64 rcd, struct mpnic_rcq_state *state,
> + struct mpnic_q_triad *qt)
> +{
> + unsigned int pg_off = FIELD_GET(MPNIC_RCD_AL_BUFF_OFF, rcd);
> + unsigned int pg_idx = FIELD_GET(MPNIC_RCD_AL_BUFF_ID, rcd);
> + unsigned int len = FIELD_GET(MPNIC_RCD_AL_BUFF_LEN, rcd);
> + bool fin = FIELD_GET(MPNIC_RCD_AL_PAGE_FIN, rcd);
> + struct xdp_buff *buff = &state->pkt.buff;
> + unsigned int truesz;
> + struct page *page;
> +
> + page = mpnic_page_pool_get(&state->payld, &qt->sub1, pg_idx);
> + qt->sub1.head = (pg_idx + 1) & qt->sub1.size_mask;
> +
> + truesz = (fin ? page_size(page) : ALIGN(pg_off + len, 128)) - pg_off;
> +
> + page_pool_dma_sync_for_cpu(qt->sub1.page_pool, page, pg_off, truesz);
> +
> + if (!xdp_buff_add_frag(buff, page_to_netmem(page), pg_off, len,
> + truesz)) {
[Severity: Medium]
Will this crash if a PAY_AL descriptor arrives before a HDR_AL descriptor?
If the hardware delivers a malformed sequence or drops a descriptor,
state->pkt.buff.data_hard_start might be NULL here. The call to
xdp_buff_add_frag() would then calculate the skb_shared_info pointer relative
to NULL minus SKB_DATA_ALIGN. Writing to sinfo->nr_frags at this invalid
memory address would cause an immediate page fault.
Is there a missing check to verify an active frame was properly started?
> + state->payld.pagecnt_bias++;
> + state->pkt.add_frag_failed = true;
> + }
> +}
[ ... ]
> +static int mpnic_clean_rcq(struct mpnic_napi_vector *nv,
> + struct mpnic_q_triad *qt, int budget)
> +{
> + struct mpnic_ring *rcq = &qt->cmpl;
> + struct mpnic_rcq_state *state;
> + unsigned int packets = 0;
> + __le64 *raw_rcd, done;
> + u32 head = rcq->head;
> +
> + done = (head & (rcq->size_mask + 1)) ? 0 : cpu_to_le64(MPNIC_RCD_DONE);
> + raw_rcd = &rcq->desc[head & rcq->size_mask];
> + state = rcq->state;
> +
> + while (packets < budget) {
> + u64 rcd;
> +
> + if ((*raw_rcd & cpu_to_le64(MPNIC_RCD_DONE)) != done)
> + break;
> +
> + dma_rmb();
> +
> + rcd = le64_to_cpu(*raw_rcd);
> +
> + switch (FIELD_GET(MPNIC_RCD_TYPE, rcd)) {
> + case MPNIC_RCD_TYPE_HDR_AL:
> + if (FIELD_GET(MPNIC_RCD_HDR_SUBTYPE, rcd) ==
> + MPNIC_RCD_HDR_SUBTYPE_HDR)
> + mpnic_pkt_prepare(rcd, state, qt);
> + break;
> + case MPNIC_RCD_TYPE_PAY_AL:
> + mpnic_add_rx_frag(rcd, state, qt);
> + break;
> + case MPNIC_RCD_TYPE_META: {
> + struct sk_buff *skb = NULL;
> +
> + if (likely(!(rcd &
> + MPNIC_RCD_META_UNCORRECTABLE_ERR_MASK) &&
> + !state->pkt.add_frag_failed))
> + skb = xdp_build_skb_from_buff(&state->pkt.buff);
[Severity: Medium]
Could this trigger a NULL pointer dereference when accessing unmapped memory?
If no preceding MPNIC_RCD_TYPE_HDR_AL descriptor was received for the frame,
state->pkt.buff.data_hard_start remains NULL. The driver then blindly calls
xdp_build_skb_from_buff(), passing the uninitialized buffer to
napi_build_skb(NULL, 0). The core network stack passes NULL to ksize(), which
returns 0, leading to an integer underflow when subtracting SKB_DATA_ALIGN.
The resulting pointer is memset, causing an immediate crash.
Should we validate that a valid header descriptor was previously received
to initialize the buffer before attempting to build the SKB?
> +
> + if (likely(skb))
> + napi_gro_receive(&nv->napi, skb);
> + else
> + mpnic_put_pkt_buff(&state->pkt, true);
[ ... ]
> +static int mpnic_poll(struct napi_struct *napi, int budget)
> +{
> + struct mpnic_napi_vector *nv = container_of(napi,
> + struct mpnic_napi_vector,
> + napi);
> - int i;
> + int i, j, work_done = 0;
>
> for (i = 0; i < nv->txt_count; i++)
> mpnic_clean_tcq(nv, &nv->qt[i], budget);
>
> + if (likely(budget))
> + for (j = 0; j < nv->rxt_count; j++, i++)
> + work_done += mpnic_clean_rcq(nv, &nv->qt[i],
> + budget - work_done);
[Severity: High]
Can this permanently bias NAPI budget allocation and starve higher-indexed Rx
queues?
The loop unconditionally starts at index 0 and passes the remaining NAPI
budget (budget - work_done) to each subsequent queue. If the first queue
continuously exhausts the entire budget under heavy load, budget - work_done
becomes 0 for the remaining queues.
Because the loop does not remember its position across NAPI poll cycles, it
will always restart at queue 0, permanently starving higher-indexed queues.
Could a high rate of traffic to the first queue cause a complete denial of
service for flows hashed to other queues on the same NAPI vector?
> +
> for (i = 0; i < nv->txt_count; i++)
> mpnic_commit_cq_head(&nv->qt[i].cmpl);
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260924-linux-mpnic-v2-0-4badc9b58b9e@gmail.com?part=8
next prev parent reply other threads:[~2026-09-26 0:36 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-25 0:35 [PATCH net-next v2 0/8] eth: mpnic: initial support for Meta Platforms NIC Daniel Zahka
2026-09-25 0:35 ` [PATCH net-next v2 1/8] eth: mpnic: add scaffolding " Daniel Zahka
2026-09-26 0:36 ` sashiko-bot
2026-09-28 0:01 ` netdev-bot+sashiko
2026-09-28 12:13 ` Daniel Zahka
2026-09-25 0:35 ` [PATCH net-next v2 2/8] eth: mpnic: add register init for the device Daniel Zahka
2026-09-28 0:01 ` netdev-bot+sashiko
2026-09-28 12:14 ` Daniel Zahka
2026-09-25 0:35 ` [PATCH net-next v2 3/8] eth: mpnic: allocate MSI-X vectors Daniel Zahka
2026-09-28 0:01 ` netdev-bot+sashiko
2026-09-28 16:01 ` Daniel Zahka
2026-09-25 0:35 ` [PATCH net-next v2 4/8] eth: mpnic: implement Tx queue allocation and cleanup Daniel Zahka
2026-09-26 0:36 ` sashiko-bot
2026-09-28 0:01 ` netdev-bot+sashiko
2026-09-28 14:46 ` Daniel Zahka
2026-09-25 0:35 ` [PATCH net-next v2 5/8] eth: mpnic: start and stop the Tx HW queues Daniel Zahka
2026-09-26 0:36 ` sashiko-bot
2026-09-28 0:01 ` netdev-bot+sashiko
2026-09-28 15:00 ` Daniel Zahka
2026-09-25 0:35 ` [PATCH net-next v2 6/8] eth: mpnic: add a netdevice and basic Tx handling Daniel Zahka
2026-09-28 0:01 ` netdev-bot+sashiko
2026-09-28 15:10 ` Daniel Zahka
2026-09-25 0:35 ` [PATCH net-next v2 7/8] eth: mpnic: implement Rx queue allocation and cleanup Daniel Zahka
2026-09-28 0:01 ` netdev-bot+sashiko
2026-09-28 15:11 ` Daniel Zahka
2026-09-25 0:35 ` [PATCH net-next v2 8/8] eth: mpnic: add basic Rx handling Daniel Zahka
2026-09-26 0:36 ` sashiko-bot [this message]
2026-09-28 0:01 ` netdev-bot+sashiko
2026-09-28 15:17 ` Daniel Zahka
2026-09-29 2:03 ` Jakub Kicinski
2026-09-28 18:16 ` [PATCH net-next v2 0/8] eth: mpnic: initial support for Meta Platforms NIC Daniel Zahka
2026-09-29 8:50 ` patchwork-bot+netdevbpf
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=20260926003603.45E161F000FF@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel.zahka@gmail.com \
--cc=sashiko-reviews@lists.linux.dev \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox