mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
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.
> 
> 

      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®