From: sashiko-bot@kernel.org
To: "Yishai Hadas" <yishaih@nvidia.com>
Cc: linux-rdma@vger.kernel.org
Subject: Re: [PATCH rdma-next 13/23] RDMA/mlx5: Keep the UMR QP failed once a forged CQE is detected
Date: Wed, 04 Nov 2026 16:43:48 +0000 [thread overview]
Message-ID: <sashiko-outbox-197666@kernel.org> (raw)
In-Reply-To: <20261103163949.1554-14-yishaih@nvidia.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] RDMA/mlx5: unserialized mlx5r_umr_recover() and ERR state overwrite
--
commit a4c9a11e36d34c06e5a6a8bce8ad178d57157c1a
Author: Yishai Hadas <yishaih@nvidia.com>
RDMA/mlx5: Keep the UMR QP failed once a forged CQE is detected
This commit updates mlx5r_umr_recover() to transition umrc->state using
cmpxchg() when mlx5_ib_adversarial_mode is enabled so that a concurrent
transition to MLX5_UMR_STATE_ERR by the CQ poller is not overwritten back to
MLX5_UMR_STATE_RECOVER or MLX5_UMR_STATE_ACTIVE.
> 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.
> + */
> +static bool mlx5r_umr_move_state(struct umr_common *umrc, unsigned int from,
> + unsigned int to)
> +{
> + if (!mlx5_ib_adversarial_mode) {
> + umrc->state = to;
> + return true;
> + }
> +
> + return cmpxchg(&umrc->state, from, to) != MLX5_UMR_STATE_ERR;
> +}
> +
> static int mlx5r_umr_recover(struct mlx5_ib_dev *dev, u32 mkey,
> struct mlx5r_umr_context *umr_context,
> struct mlx5r_umr_wqe *wqe, bool with_data)
> @@ -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);
>
> @@ -387,7 +408,9 @@ static int mlx5r_umr_recover(struct mlx5_ib_dev *dev, u32 mkey,
> goto err;
> }
>
> - umrc->state = MLX5_UMR_STATE_ACTIVE;
> + if (!mlx5r_umr_move_state(umrc, MLX5_UMR_STATE_RECOVER,
> + MLX5_UMR_STATE_ACTIVE))
> + return -EFAULT;
[Severity: High]
Can a hostile NIC still cause concurrent mlx5r_umr_recover() executions and
overwrite MLX5_UMR_STATE_ERR back to MLX5_UMR_STATE_ACTIVE?
In mlx5_ib_adversarial_mode, up to 64 threads can concurrently post UMR WRs
in mlx5r_umr_post_send_wait() under umrc->sem, placing their contexts into
umrc->pending[]. If a hostile NIC returns valid-header MLX5_CQE_REQ_ERR
completions (matching qpn, sop == MLX5_OPCODE_UMR, and sequential wqe_ctr)
with a non-flush syndrome (such as MLX5_CQE_SYNDROME_LOCAL_QP_OP_ERR, where
wc->status != IB_WC_WR_FLUSH_ERR) for multiple in-flight WRs,
mlx5_ib_poll_one_umr() accepts each CQE and unconditionally writes
MLX5_UMR_STATE_RECOVER:
drivers/infiniband/hw/mlx5/cq.c:mlx5_ib_poll_one_umr() {
...
} else {
/* Copy the CQE, so its syndrome is read once */
err_cqe = *(struct mlx5_err_cqe *)cqe64;
mlx5_handle_error_cqe(dev, &err_cqe, wc);
/* As in the generic path, a real failure starts the recovery */
if (wc->status != IB_WC_WR_FLUSH_ERR)
umrc->state = MLX5_UMR_STATE_RECOVER;
}
}
Multiple waiters in mlx5r_umr_post_send_wait() then wake up with
umr_context.status != IB_WC_WR_FLUSH_ERR and call mlx5r_umr_recover().
Because mlx5r_umr_recover() only holds umrc->lock across the initial state
check and treats umrc->state == MLX5_UMR_STATE_RECOVER as the normal entry
state without serializing recovery callers, multiple threads can run
mlx5r_umr_recover() at the same time.
This appears to allow two problems:
1. If one recovery thread fails at the err label in mlx5r_umr_recover(), it
sets umrc->state = MLX5_UMR_STATE_ERR without stopping cq->poll_one:
drivers/infiniband/hw/mlx5/umr.c:mlx5r_umr_recover() {
...
err:
umrc->state = MLX5_UMR_STATE_ERR;
return err;
}
When mlx5_ib_poll_one_umr() subsequently processes another non-flush error
CQE for an in-flight WR or barrier WR, its plain store overwrites
MLX5_UMR_STATE_ERR back to MLX5_UMR_STATE_RECOVER, allowing a concurrent
recovery thread's mlx5r_umr_move_state(umrc, MLX5_UMR_STATE_RECOVER,
MLX5_UMR_STATE_ACTIVE) call to succeed and reopen the UMR path to
MLX5_UMR_STATE_ACTIVE.
2. When the first recovery thread's barrier WR completes and it calls
ib_modify_qp(umrc->qp, IB_QPS_RESET), __mlx5_ib_modify_qp() resets the QP
and zeroes qp->sq.head, qp->sq.tail, qp->sq.cur_post, and qp->sq.last_poll
while the second recovery thread's barrier WR is still queued in
umrc->pending and sleeping in wait_for_completion(&umr_context->done). Does
that desynchronize umrc->pending from qp->sq and leave the second thread
hung in wait_for_completion() while holding umrc->sem, since even the
internal-error software flush in sw_comp() walks from last_poll to head?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261103163949.1554-1-yishaih@nvidia.com?part=13
next prev parent reply other threads:[~2026-11-04 16:43 UTC|newest]
Thread overview: 49+ 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-04 16:43 ` sashiko-bot
2026-11-03 16:39 ` [PATCH rdma-next 02/23] net/mlx5: Derive adversarial mode from CC guest memory encryption Yishai Hadas
2026-11-04 16:43 ` sashiko-bot
2026-11-03 16:39 ` [PATCH rdma-next 03/23] net/mlx5: Add capability filtering in adversarial mode Yishai Hadas
2026-11-04 16:43 ` sashiko-bot
2026-11-03 16:39 ` [PATCH rdma-next 04/23] net/mlx5: Add macros for reading log-based caps Yishai Hadas
2026-11-04 16:43 ` sashiko-bot
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-04 16:43 ` sashiko-bot
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-04 16:43 ` sashiko-bot
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-04 16:43 ` sashiko-bot
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-04 16:43 ` sashiko-bot
2026-11-03 16:39 ` [PATCH rdma-next 09/23] RDMA/mlx5: Remove duplicate mlx5_ib_umr_context struct Yishai Hadas
2026-11-04 16:43 ` sashiko-bot
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-04 16:43 ` sashiko-bot
2026-11-03 16:39 ` [PATCH rdma-next 11/23] RDMA/mlx5: Add shadow FIFO infrastructure for UMR completions Yishai Hadas
2026-11-04 16:43 ` sashiko-bot
2026-11-03 16:39 ` [PATCH rdma-next 12/23] RDMA/mlx5: Verify UMR CQ polling against a hostile NIC Yishai Hadas
2026-11-04 16:43 ` sashiko-bot
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-04 16:43 ` sashiko-bot [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-04 16:43 ` sashiko-bot
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-04 16:43 ` sashiko-bot
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-04 16:43 ` sashiko-bot
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-04 16:43 ` sashiko-bot
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-04 16:43 ` sashiko-bot
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-04 16:43 ` sashiko-bot
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-04 16:43 ` sashiko-bot
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-04 16:43 ` sashiko-bot
2026-11-03 16:39 ` [PATCH rdma-next 22/23] RDMA/core: Report and enforce adversarial mode via GET_CONTEXT Yishai Hadas
2026-11-04 16:43 ` sashiko-bot
2026-11-03 16:39 ` [PATCH rdma-next 23/23] RDMA/mlx5: Advertise adversarial mode via ib_device::adversarial_mode Yishai Hadas
2026-11-04 16:43 ` sashiko-bot
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=sashiko-outbox-197666@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--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