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 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.