From: Nitin Shetty J <nshettyj@marvell.com>
To: Paolo Abeni <pabeni@redhat.com>
Cc: <netdev@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
<rkudurumalla@marvell.com>, <sgoutham@marvell.com>,
<rkannoth@marvell.com>, <gakula@marvell.com>,
<sbhatta@marvell.com>, <andrew+netdev@lunn.ch>,
<davem@davemloft.net>, <edumazet@google.com>, <kuba@kernel.org>,
<horms@kernel.org>, <nshettyj@marvell.com>
Subject: Re: [PATCH net v2] octeontx2-af: Fix BPID leak in nix_bp_enable()
Date: Mon, 28 Sep 2026 12:15:49 +0530 [thread overview]
Message-ID: <aroNHaLv6y14+5MY@kernel-ep2> (raw)
In-Reply-To: <20260915131714.165308-1-pabeni@redhat.com>
On 2026-09-15 at 18:47:14, Paolo Abeni (pabeni@redhat.com) wrote:
> This is an AI-generated review of your patch. The human sending this
> email has considered the AI review valid, or at least plausible.
> Full review at: https://netdev-ai.bots.linux.dev/sashiko/
> ---
> octeontx2-af: Fix BPID leak in nix_bp_enable()
>
> For LBK interfaces rvu_nix_get_bpid() takes a BPID from the free pool on
> every call, and nix_bp_enable() used to call it once before the loop and
> once more after the last channel was programmed. The patch moves the
> allocation into the loop body and rejects req->chan_cnt == 0 upfront.
>
> > diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
> > index 153eb57bad067..3a43432d29c15 100644
> > --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
> > +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
> > @@ -764,19 +764,25 @@ static int nix_bp_enable(struct rvu *rvu,
> > if (cpt_link && !rvu->hw->cpt_links)
> > return 0;
> >
> > + if (!req->chan_cnt)
> > + return NIX_AF_ERR_INVALID_BPID_REQ;
>
> [Severity: High]
> This isn't a bug introduced by this patch, but since the change adds request
> validation here, is the companion bound on req->chan_base / req->chan_cnt
> also needed for LBK?
>
> rvu_nix_get_bpid() range-checks the channel interval only for the CGX and
> SDP cases:
>
> case NIX_INTF_TYPE_CGX:
> if ((req->chan_base + req->chan_cnt) > NIX_BPIDS_PER_LMAC)
> return NIX_AF_ERR_INVALID_BPID_REQ;
> ...
> case NIX_INTF_TYPE_SDP:
> if ((req->chan_base + req->chan_cnt) > bp->sdp_bpid_cnt)
> return NIX_AF_ERR_INVALID_BPID_REQ;
>
> The NIX_INTF_TYPE_LBK case has no such check, and nix_interface_init() gives
> an LBK VF exactly one RX channel (pfvf->rx_chan_cnt = 1), while req->chan_base
> is a u16 copied straight out of the mailbox region.
>
> So chan_base = pfvf->rx_chan_base + req->chan_base can be any 16-bit value,
> and each iteration does a read-modify-write of the AF-global register
> NIX_AF_RX_CHANX_CFG(chan_v), which expands to 0x1A30 | (a) << 15. With
> req->chan_base near 0xFFF0 the offset reaches roughly 0x7FFF8000, well past
> the 1 << 28 per-block stride assumed by rvu_write64():
>
> writeq(val, rvu->afreg_base + ((block << 28) | offset));
>
> Can an LBK VF therefore reprogram the backpressure configuration of channels
> owned by other PF/VFs (arming them against a foreign BPID with BIT_ULL(16)
> set), or push the access outside the intended NIX register window?
>
Since it is exisiting issue will submit separate patch.
> > pfvf = rvu_get_pfvf(rvu, pcifunc);
> > blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc);
> >
> > - bpid_base = rvu_nix_get_bpid(rvu, req, type, chan_id);
> > chan_base = pfvf->rx_chan_base + req->chan_base;
> > - bpid = bpid_base;
> > + bpid_base = -1;
> >
> > for (chan = chan_base; chan < (chan_base + req->chan_cnt); chan++) {
> > + bpid = rvu_nix_get_bpid(rvu, req, type, chan_id);
> > if (bpid < 0) {
> > dev_warn(rvu->dev, "Fail to enable backpressure\n");
> > return -EINVAL;
> > }
>
> [Severity: High]
> Now that the allocation happens per iteration, does this bare return leak the
> BPIDs already taken for the earlier channels?
>
> For LBK, each call consumes one entry of the finite free pool and records
> ownership:
>
> case NIX_INTF_TYPE_LBK:
> /* Alloc bpid from the free pool */
> mutex_lock(&rvu->rsrc_lock);
> bpid = rvu_alloc_rsrc(&bp->bpids);
> if (bpid < 0) {
> mutex_unlock(&rvu->rsrc_lock);
> return NIX_AF_ERR_INVALID_BPID;
> }
> bp->fn_map[bpid] = req->hdr.pcifunc;
> bp->ref_cnt[bpid]++;
>
> A request with req->chan_cnt larger than the number of free pool entries
> fails deterministically once rvu_alloc_rsrc() returns -ENOSPC. At that point
> iterations 0..i-1 have already allocated BPIDs and written them into
> NIX_AF_RX_CHANX_CFG with the enable bit set, and this path returns without
> freeing them or clearing the enable bit.
>
> The response is also left zeroed (otx2_mbox_alloc_msg_rsp() memsets the msg
> region and rsp->chan_cnt is only set at the end of the function), so the
> requester learns no channel/BPID mapping and will not send a matching
> NIX_BP_DISABLE. Does that leave the BPIDs marked used with fn_map/ref_cnt
> set until FLR, and the affected RX channels armed against BPIDs that no aura
> maps?
>
> Would an unwind loop that frees the BPIDs and clears BIT_ULL(16) for the
> channels programmed so far be appropriate here?
>
will fix it in next patch version
> >
> > + if (bpid_base < 0)
> > + bpid_base = bpid;
> > +
>
> [Severity: Medium]
> Only the first allocation is remembered here, but the response is built from
> it arithmetically:
>
> for (chan = 0; chan < req->chan_cnt; chan++) {
> /* Map channel and bpid assign to it */
> rsp->chan_bpid[chan] = ((req->chan_base + chan) & 0x7F) << 10 |
> (bpid_base & 0x3FF);
> if (req->bpid_per_chan)
> bpid_base++;
> }
>
> Does this diverge from what was actually programmed for LBK?
>
> The mailbox contract in mbox.h says:
>
> u8 bpid_per_chan;
> /* bpid_per_chan = 0 assigns single bp id for range of channels */
> /* bpid_per_chan = 1 assigns separate bp id for each channel */
>
> The LBK branch of rvu_nix_get_bpid() ignores req->bpid_per_chan and always
> allocates a fresh pool entry. With bpid_per_chan == 0 and chan_cnt > 1, each
> NIX_AF_RX_CHANX_CFG gets a different BPID while rsp->chan_bpid[] reports
> bpid_base for every channel. The requester then wires up only bpid_base:
>
> drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c:mbox_handler_nix_bp_enable() {
> for (chan = 0; chan < rsp->chan_cnt; chan++) {
> chan_id = ((rsp->chan_bpid[chan] >> 10) & 0x7F);
> pfvf->bpid[chan_id] = rsp->chan_bpid[chan] & 0x3FF;
> }
> }
>
> With bpid_per_chan == 1 the response assumes bpid_base, bpid_base + 1, ...,
> but rvu_alloc_rsrc() returns the first free bit of a shared bitmap:
>
> id = find_first_zero_bit(rsrc->bmap, rsrc->max);
> if (id >= rsrc->max)
> return -ENOSPC;
> __set_bit(id, rsrc->bmap);
>
> and rvu_nix_get_bpid() takes and drops rvu->rsrc_lock once per channel, so a
> fragmented pool or an interleaved allocation by another LBK function gives
> non-contiguous BPIDs. Can the reported map then name a BPID owned by a
> different pcifunc?
>
> For bpid_per_chan == 0, would allocating once per request (and reporting the
> BPIDs actually written) match the documented behaviour better than "exactly
> once per channel actually programmed"?
>
will fix it in next patch version
> > chan_v = nix_get_channel(chan, cpt_link);
> >
> > cfg = rvu_read64(rvu, blkaddr, NIX_AF_RX_CHANX_CFG(chan_v));
> > @@ -784,7 +790,6 @@ static int nix_bp_enable(struct rvu *rvu,
> > rvu_write64(rvu, blkaddr, NIX_AF_RX_CHANX_CFG(chan_v),
> > cfg | (bpid & GENMASK_ULL(8, 0)) | BIT_ULL(16));
> > chan_id++;
> > - bpid = rvu_nix_get_bpid(rvu, req, type, chan_id);
> > }
> >
> > for (chan = 0; chan < req->chan_cnt; chan++) {
>
> [Severity: Critical]
> This is a pre-existing issue, but it interacts with the new mid-loop error
> return above, so it seems worth raising here.
>
> nix_bp_disable() recovers the BPID to release from the channel register:
>
> if (type == NIX_INTF_TYPE_LBK) {
> bpid = cfg & GENMASK(8, 0);
> mutex_lock(&rvu->rsrc_lock);
> rvu_free_rsrc(&bp->bpids, bpid - bp->free_pool_base);
>
> nix_setup_bpids() makes free_pool_base strictly positive:
>
> bp->free_pool_base = bp->cgx_bpid_cnt + bp->sdp_bpid_cnt +
> NIX_BPIDS_PER_CPT;
>
> So for any channel whose CFG BPID field is below free_pool_base - the reset
> value 0 on a channel that was never enabled, the tail channels left
> unprogrammed by the new error return in nix_bp_enable(), or a CGX-range BPID
> belonging to another function - the second argument is negative.
>
> rvu_free_rsrc() does not check it:
>
> void rvu_free_rsrc(struct rsrc_bmap *rsrc, int id)
> {
> if (!rsrc->bmap)
> return;
>
> __clear_bit(id, rsrc->bmap);
> }
>
> and generic___clear_bit() takes an unsigned long:
>
> unsigned long mask = BIT_MASK(nr);
> unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
>
> *p &= ~mask;
>
> Can this write outside bp->bpids.bmap? Since nothing bounds chan_base /
> chan_cnt for LBK, a VF sending NIX_BP_DISABLE over channels it never enabled
> appears to reach this with bpid == 0. Should nix_bp_disable() validate that
> the register-derived BPID falls inside the free pool range before converting
> it to a pool index?
will fix it in next patch version
> --
> This is an AI-generated review.
>
>
prev parent reply other threads:[~2026-09-28 6:46 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-10 3:16 nshettyj
2026-09-15 13:17 ` Paolo Abeni
2026-09-28 6:45 ` Nitin Shetty J [this message]
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=aroNHaLv6y14+5MY@kernel-ep2 \
--to=nshettyj@marvell.com \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=gakula@marvell.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=rkannoth@marvell.com \
--cc=rkudurumalla@marvell.com \
--cc=sbhatta@marvell.com \
--cc=sgoutham@marvell.com \
/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
all inboxes | Powered by JetHome®