Netdev List
 help / color / mirror / Atom feed
From: netdev-bot+sashiko@kernel.org
To: yishaih@nvidia.com
Cc: jgg@ziepe.ca, leon@kernel.org, linux-rdma@vger.kernel.org,
	netdev@vger.kernel.org, saeedm@nvidia.com, tariqt@nvidia.com,
	mbloch@nvidia.com, kuba@kernel.org, pabeni@redhat.com,
	edumazet@kernel.org, davem@davemloft.net, andrew+netdev@lunn.ch,
	dtatulea@nvidia.com, moshe@nvidia.com, maorg@nvidia.com
Subject: Re: [PATCH rdma-next 13/23] RDMA/mlx5: Keep the UMR QP failed once a forged CQE is detected
Date: Sat, 07 Nov 2026 20:24:56 +0000	[thread overview]
Message-ID: <179408309600.994134.14553230868146108147@kernel.org> (raw)
In-Reply-To: <20261103163949.1554-14-yishaih@nvidia.com>

Thank you for your contribution! Sashiko AI review found 2 potential
issue(s) to consider.

Critical: 0 · High: 0 · Medium: 2 · Low: 0

If you believe none of the issues are legitimate, please reply to each
issue of Medium severity or higher and explain why the AI is wrong.
If any of them are legitimate and you plan to respin, please let patchwork
know by including "pw-bot: cr" as a separate line at the end of your reply
(one such reply per series is enough).

- [Medium] In adversarial mode, mlx5r_umr_recover()
  (drivers/infiniband/hw/mlx5/umr.c) checks for MLX5_UMR_STATE_ERR at…
- [Medium] The new comment on mlx5r_umr_move_state() (umr.c:338-343) and
  the commit message both say that in adversarial mode ERR is a final…

--

RDMA/mlx5: Keep the UMR QP failed once a forged CQE is detected

In adversarial mode, this commit changes mlx5r_umr_recover() to move the
UMR state with cmpxchg(): ACTIVE to RECOVER on entry and RECOVER to
ACTIVE at the end. The goal is to stop recovery from overwriting an
MLX5_UMR_STATE_ERR that the CQ poller sets on a forged CQE. Outside
adversarial mode the transitions are unchanged.

> diff --git a/drivers/infiniband/hw/mlx5/umr.c b/drivers/infiniband/hw/mlx5/umr.c
> index b0f00d4bc93ca..086b397b830c6 100644
> --- a/drivers/infiniband/hw/mlx5/umr.c
> +++ b/drivers/infiniband/hw/mlx5/umr.c
> @@ -335,6 +335,23 @@ static int mlx5r_umr_post_send(struct ib_qp *ibqp, u32 mkey,
>  	return err;
>  }
>  
> +/*
> + * Move the UMR state from @from to @to. In adversarial_mode ERR is a final
> + * state: it can be set concurrently by the CQ poller, so the move is atomic
> + * and does not replace it. Returns false if ERR was found, and true
> + * otherwise. Outside adversarial_mode this is the plain store it always was.
> + */

[Severity: Medium]
Is ERR really final here? Only the transitions in mlx5r_umr_recover()
were converted to cmpxchg(). mlx5_ib_poll_one_umr() in cq.c still does a
plain store for every validated non-flush error CQE:

drivers/infiniband/hw/mlx5/cq.c:mlx5_ib_poll_one_umr() {
    ...
		if (wc->status != IB_WC_WR_FLUSH_ERR)
			umrc->state = MLX5_UMR_STATE_RECOVER;
    ...
}

That store can overwrite the ERR written by the err: label in
mlx5r_umr_recover(), and that label does not stop the poller:

err:
	umrc->state = MLX5_UMR_STATE_ERR;
	return err;

Could a hostile NIC reopen the UMR path with a sequence like this?

1. Waiters A and B each post a UMR while the state is ACTIVE.

2. The NIC returns validated non-flush error CQEs for both. A and B enter
   mlx5r_umr_recover(), find the state already RECOVER, skip the entry
   cmpxchg, and post barriers WQE3 and WQE4.

3. The NIC completes WQE3. A moves the QP to RESET, the NIC fails
   RST2INIT, and A's err: label stores ERR.

4. The NIC returns a non-flush error CQE for WQE4. It passes the opcode,
   QPN, sop, wqe_ctr (FIFO head) and wqe_head checks, so the poller
   stores RECOVER over ERR.

5. B's RESET and RST2RTS succeed, and B's cmpxchg(RECOVER->ACTIVE) also
   succeeds, so the UMR path is ACTIVE again.

The generic store of RECOVER in mlx5_poll_one() has the same problem at
this commit. The later commit "RDMA/mlx5: Block generic CQ poll path in
adversarial mode" closes that path by making mlx5_poll_one() return
-EOPNOTSUPP in adversarial mode before the store is reached.

Would a cmpxchg(ACTIVE->RECOVER) in mlx5_ib_poll_one_umr() fix this? If
not, should the comment say that only an ERR set on a forged CQE is
final?

[ ... ]

> @@ -353,7 +370,11 @@ static int mlx5r_umr_recover(struct mlx5_ib_dev *dev, u32 mkey,
>  	if (umrc->state != MLX5_UMR_STATE_RECOVER) {
>  		mlx5_ib_warn(dev, "UMR recovery encountered an unexpected state=%d\n",
>  			     umrc->state);
> -		umrc->state = MLX5_UMR_STATE_RECOVER;
> +		if (!mlx5r_umr_move_state(umrc, MLX5_UMR_STATE_ACTIVE,
> +					  MLX5_UMR_STATE_RECOVER)) {
> +			mutex_unlock(&umrc->lock);
> +			return -EFAULT;
> +		}
>  	}
>  	mutex_unlock(&umrc->lock);

[Severity: Medium]
What happens if the poller detects a forged CQE after this
mutex_unlock()?

mlx5_ib_poll_one_umr() never takes umrc->lock. It sets ERR under cq->lock
and only queues the forced health work:

	umrc->state = MLX5_UMR_STATE_ERR;
	cq->poll_one = mlx5_ib_poll_one_stopped;
	mlx5_trigger_health_work_force(dev->mdev);

After the unlock, mlx5r_umr_recover() does not look at umrc->state again
until the final cmpxchg, so recovery continues:

mlx5r_umr_recover()
  mlx5r_umr_post_send()
    only checks mdev->state, writes the barrier WQE and rings the doorbell
  wait_for_completion()
  ib_modify_qp(umrc->qp, &attr, IB_QP_STATE)  /* RESET */
    __mlx5_ib_modify_qp()->mlx5_ib_cq_clean() sweeps the stopped UMR CQ
  mlx5r_umr_qp_rst2rts()
    RST2INIT/INIT2RTR/RTR2RTS put the hardware UMR QP back in RTS
  mlx5r_umr_move_state(umrc, MLX5_UMR_STATE_RECOVER, MLX5_UMR_STATE_ACTIVE)
    first point where ERR is seen

The NIC controls CQE timing. It can complete the barrier with a valid CQE
and then forge one while recovery is in the RESET/RTS steps. All of this
can happen before the forced health work moves the device to
MLX5_DEVICE_STATE_INTERNAL_ERROR.

umrc->state stays ERR, so mlx5r_umr_post_send_wait() still refuses new
UMRs. Even so, in this window the subject line "Keep the UMR QP failed",
the existing comment "don't revive the QP" in mlx5r_umr_recover(), and
this part of the commit message don't seem fully met:

  This keeps new UMRs away from the NIC until the forced health recovery
  moves the device to MLX5_DEVICE_STATE_INTERNAL_ERROR

In adversarial mode, should ERR be checked again at these points?

- before the barrier post, perhaps inside mlx5r_umr_post_send() under
  qp->sq.lock
- after wait_for_completion()
- before each ib_modify_qp() step

[ ... ]

-- 
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261103163949.1554-1-yishaih%40nvidia.com

  reply	other threads:[~2026-11-07 20:24 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-03 16:39 [PATCH rdma-next 00/23] mlx5: Adversarial mode for confidential computing guests Yishai Hadas
2026-11-03 16:39 ` [PATCH rdma-next 01/23] net/mlx5: Add mlx5_trigger_health_work_force() Yishai Hadas
2026-11-07 20:24   ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 02/23] net/mlx5: Derive adversarial mode from CC guest memory encryption Yishai Hadas
2026-11-07 20:24   ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 03/23] net/mlx5: Add capability filtering in adversarial mode Yishai Hadas
2026-11-07 20:24   ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 04/23] net/mlx5: Add macros for reading log-based caps Yishai Hadas
2026-11-07 20:24   ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 05/23] RDMA/mlx5: Reject QP transport types not enabled by FW capability Yishai Hadas
2026-11-07 20:24   ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 06/23] RDMA/mlx5: Require IB_QPT_DRIVER for the DC vendor QP types Yishai Hadas
2026-11-07 20:24   ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 07/23] RDMA/mlx5: Derive mlx5_ib_adversarial_mode global from mlx5_core adversarial API Yishai Hadas
2026-11-07 20:24   ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 08/23] RDMA/core: Suppress kverbs_provider for adversarial_mode devices Yishai Hadas
2026-11-03 19:03   ` Jacob Moroni
2026-11-03 19:07     ` Jason Gunthorpe
2026-11-07 20:24   ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 09/23] RDMA/mlx5: Remove duplicate mlx5_ib_umr_context struct Yishai Hadas
2026-11-03 16:39 ` [PATCH rdma-next 10/23] RDMA/mlx5: Introduce per-CQ poll_one hook in mlx5_ib_cq Yishai Hadas
2026-11-07 20:24   ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 11/23] RDMA/mlx5: Add shadow FIFO infrastructure for UMR completions Yishai Hadas
2026-11-07 20:24   ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 12/23] RDMA/mlx5: Verify UMR CQ polling against a hostile NIC Yishai Hadas
2026-11-07 20:24   ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 13/23] RDMA/mlx5: Keep the UMR QP failed once a forged CQE is detected Yishai Hadas
2026-11-07 20:24   ` netdev-bot+sashiko [this message]
2026-11-03 16:39 ` [PATCH rdma-next 14/23] RDMA/mlx5: Block generic CQ poll path in adversarial mode Yishai Hadas
2026-11-07 20:24   ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 15/23] RDMA/core: Set the CQ comp_handler after its poll context is set up Yishai Hadas
2026-11-07 20:24   ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 16/23] RDMA/mlx5: Ignore completion events for a CQ without a handler Yishai Hadas
2026-11-07 20:25   ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 17/23] RDMA/mlx5: Validate EQE port and GSI port before indexing devr.ports[] Yishai Hadas
2026-11-07 20:25   ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 18/23] RDMA/mlx5: Validate firmware RQ/SQ state before sqrq_trans[] lookup Yishai Hadas
2026-11-07 20:25   ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 19/23] RDMA/mlx5: Clamp log_max_cq_sz shift in CQ size checks Yishai Hadas
2026-11-07 20:25   ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 20/23] RDMA/mlx5: Clamp log_max_* shifts in QP and WQ limit checks Yishai Hadas
2026-11-07 20:25   ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 21/23] RDMA/mlx5: Clamp log_max_* shifts in query_device and ucontext paths Yishai Hadas
2026-11-07 20:25   ` netdev-bot+sashiko
2026-11-03 16:39 ` [PATCH rdma-next 22/23] RDMA/core: Report and enforce adversarial mode via GET_CONTEXT Yishai Hadas
2026-11-03 16:39 ` [PATCH rdma-next 23/23] RDMA/mlx5: Advertise adversarial mode via ib_device::adversarial_mode Yishai Hadas
2026-11-07 20:25   ` 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=179408309600.994134.14553230868146108147@kernel.org \
    --to=netdev-bot+sashiko@kernel.org \
    --cc=andrew+netdev@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=dtatulea@nvidia.com \
    --cc=edumazet@kernel.org \
    --cc=jgg@ziepe.ca \
    --cc=kuba@kernel.org \
    --cc=leon@kernel.org \
    --cc=linux-rdma@vger.kernel.org \
    --cc=maorg@nvidia.com \
    --cc=mbloch@nvidia.com \
    --cc=moshe@nvidia.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=saeedm@nvidia.com \
    --cc=tariqt@nvidia.com \
    --cc=yishaih@nvidia.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