Linux RDMA and InfiniBand development
 help / color / mirror / Atom feed
* [PATCH rdma-next v3 0/7] RDMA/irdma: Adopt robust udata
@ 2026-07-02 17:06 Jacob Moroni
  2026-07-02 17:06 ` [PATCH rdma-next v3 1/7] RDMA/core: Add ib_no_udata_io() helper Jacob Moroni
                   ` (8 more replies)
  0 siblings, 9 replies; 11+ messages in thread
From: Jacob Moroni @ 2026-07-02 17:06 UTC (permalink / raw)
  To: tatyana.e.nikolova, jgg, leon; +Cc: linux-rdma, Jacob Moroni

This series brings irdma up to uverbs_robust_udata compliance.

The driver has been audited to confirm that:

  1. Methods which do not accept udata input perform an explicit
     check for no (or zero value) input.

  2. Methods which do accept input perform the correct validation
     to ensure that additional udata beyond the kernel's current
     ABI definition is zero, and to enforce the required minimum
     length.

  3. Methods which do not return udata responses use the proper
     helper.

The irdma driver is backwards compatible with the legacy i40iw
provider, so special care was taken to avoid breaking any legacy
binaries, as there were some small differences in the ABI/semantics.

This has passed the rdma-unit-test suite using the normal irdma
provider from upstream rdma-core.

NOTE: This series is based on a few irdma bug fix patches
      which have not yet been merged:

- RDMA/irdma: Prevent user-triggered null deref on QP create
  https://patchwork.kernel.org/project/linux-rdma/list/?series=1113053
     
- RDMA/irdma: Prevent premature deregistration of user ring MRs
  https://patchwork.kernel.org/project/linux-rdma/list/?series=1113648

Changes in v3:
* Add ib_no_udata_io helper to more easily handle the
  common case of no input/no output ops.
* Fixed regression in create_qp failure path caught by sashiko.
* Rebased on top of previous posted irdma fixes.
* Fixed an additional latent legacy compat bug in create_qp.
* Added missing response buffer clearing for reg/rereg_user_mr.
Changes in v2:
* Fixed Sashiko findings:
  - Moved ib_respond_empty_udata to beginning of most
    methods to close gaps where it could previously
    return 0 without calling ib_respond_empty_udata. This
    also fixes issues where the ib_respond_empty_udata
    call itself could fail, which may leave resources
    in an inconsistent state (kernel believes object
    is alive, but driver resources have been cleaned up).
  - Moved input validation to beginning of modify_qp
    methods to close gaps where the op could be invoked
    with udata but without input checking.
  - Fixed a QPN leak that could occur during QP create
    by moving input validation earlier.

v2: https://lore.kernel.org/linux-rdma/20260629232532.2057423-1-jmoroni@google.com/
v1: https://lore.kernel.org/linux-rdma/20260627025642.4064973-1-jmoroni@google.com/T/#t

Jacob Moroni (7):
  RDMA/core: Add ib_no_udata_io() helper
  RDMA/irdma: Add checks for no udata
  RDMA/irdma: Clear udata response buffers where necessary
  RDMA/irdma: Use robust input copy helpers
  RDMA/irdma: Use robust udata helper for QP creation
  RDMA/irdma: Fix legacy i40iw compat check in create_qp
  RDMA/irdma: Enable uverbs_robust_udata compliance flag

 drivers/infiniband/hw/irdma/verbs.c | 216 +++++++++++++++++++---------
 include/rdma/uverbs_ioctl.h         |  20 +++
 include/uapi/rdma/irdma-abi.h       |   1 +
 3 files changed, 167 insertions(+), 70 deletions(-)

-- 
2.55.0.rc0.799.gd6f94ed593-goog


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH rdma-next v3 1/7] RDMA/core: Add ib_no_udata_io() helper
  2026-07-02 17:06 [PATCH rdma-next v3 0/7] RDMA/irdma: Adopt robust udata Jacob Moroni
@ 2026-07-02 17:06 ` Jacob Moroni
  2026-07-02 17:06 ` [PATCH rdma-next v3 2/7] RDMA/irdma: Add checks for no udata Jacob Moroni
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Jacob Moroni @ 2026-07-02 17:06 UTC (permalink / raw)
  To: tatyana.e.nikolova, jgg, leon; +Cc: linux-rdma, Jacob Moroni

In many cases, a driver op accepts no input data and provides
no response. This helper can be used in those handlers to
adhere to the uAPI forward/backward compat rules by failing
early if invalid udata is provided (whether input or output).

Signed-off-by: Jacob Moroni <jmoroni@google.com>
---
 include/rdma/uverbs_ioctl.h | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/include/rdma/uverbs_ioctl.h b/include/rdma/uverbs_ioctl.h
index 24fd36213023..80f3ba6663d0 100644
--- a/include/rdma/uverbs_ioctl.h
+++ b/include/rdma/uverbs_ioctl.h
@@ -1151,4 +1151,24 @@ static inline int ib_respond_empty_udata(struct ib_udata *udata)
 	return 0;
 }
 
+/**
+ * ib_no_udata_io - Ensure no input data and zero fill the response buffer
+ * @udata: The system call's ib_udata struct
+ *
+ * Driver ops which do not accept any input data and do not provide any response
+ * data may call this at the beginning of their handler to fully adhere to the
+ * uAPI forward/backward compatibility rules.
+ *
+ * Return: Negative failure code if the op should be denied, 0 otherwise.
+ */
+static inline int ib_no_udata_io(struct ib_udata *udata)
+{
+	int ret = ib_is_udata_in_empty(udata);
+
+	if (ret)
+		return ret;
+
+	return ib_respond_empty_udata(udata);
+}
+
 #endif
-- 
2.55.0.rc0.799.gd6f94ed593-goog


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH rdma-next v3 2/7] RDMA/irdma: Add checks for no udata
  2026-07-02 17:06 [PATCH rdma-next v3 0/7] RDMA/irdma: Adopt robust udata Jacob Moroni
  2026-07-02 17:06 ` [PATCH rdma-next v3 1/7] RDMA/core: Add ib_no_udata_io() helper Jacob Moroni
@ 2026-07-02 17:06 ` Jacob Moroni
  2026-07-02 17:06 ` [PATCH rdma-next v3 3/7] RDMA/irdma: Clear udata response buffers where necessary Jacob Moroni
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Jacob Moroni @ 2026-07-02 17:06 UTC (permalink / raw)
  To: tatyana.e.nikolova, jgg, leon; +Cc: linux-rdma, Jacob Moroni

Several methods do not accept udata input and do not provide
a udata response. Use the ib_no_udata_io helper to check that
the input buffers are empty and to zero fill any user response
buffers. For methods that do provide a response, enforce the
input buffer is empty using ib_is_udata_in_empty.

The irdma rdma-core provider as well as the legacy i40iw
provider were both checked to ensure they never passed any
udata to these ops.

Signed-off-by: Jacob Moroni <jmoroni@google.com>
---
 drivers/infiniband/hw/irdma/verbs.c | 66 +++++++++++++++++++++++++++--
 1 file changed, 62 insertions(+), 4 deletions(-)

diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index c8541c6c1a68..be964f777e64 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -407,6 +407,10 @@ static int irdma_alloc_pd(struct ib_pd *pd, struct ib_udata *udata)
 	u32 pd_id = 0;
 	int err;
 
+	err = ib_is_udata_in_empty(udata);
+	if (err)
+		return err;
+
 	if (udata && udata->outlen < IRDMA_ALLOC_PD_MIN_RESP_LEN)
 		return -EINVAL;
 
@@ -445,6 +449,11 @@ static int irdma_dealloc_pd(struct ib_pd *ibpd, struct ib_udata *udata)
 {
 	struct irdma_pd *iwpd = to_iwpd(ibpd);
 	struct irdma_device *iwdev = to_iwdev(ibpd->device);
+	int ret;
+
+	ret = ib_no_udata_io(udata);
+	if (ret)
+		return ret;
 
 	irdma_free_rsrc(iwdev->rf, iwdev->rf->allocated_pds, iwpd->sc_pd.pd_id);
 
@@ -537,11 +546,10 @@ static int irdma_setup_push_mmap_entries(struct irdma_ucontext *ucontext,
 }
 
 /**
- * irdma_destroy_qp - destroy qp
+ * _irdma_destroy_qp - destroy qp
  * @ibqp: qp's ib pointer also to get to device's qp address
- * @udata: user data
  */
-static int irdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
+static void _irdma_destroy_qp(struct ib_qp *ibqp)
 {
 	struct irdma_qp *iwqp = to_iwqp(ibqp);
 	struct irdma_device *iwdev = iwqp->iwdev;
@@ -573,6 +581,22 @@ static int irdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
 	if (iwqp->sc_qp.qp_uk.qp_id == 1)
 		iwdev->rf->hwqp1_rsvd = false;
 	irdma_free_qp_rsrc(iwqp);
+}
+
+/**
+ * irdma_destroy_qp - destroy qp
+ * @ibqp: qp's ib pointer also to get to device's qp address
+ * @udata: user data
+ */
+static int irdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
+{
+	int ret;
+
+	ret = ib_no_udata_io(udata);
+	if (ret)
+		return ret;
+
+	_irdma_destroy_qp(ibqp);
 
 	return 0;
 }
@@ -1127,7 +1151,7 @@ static int irdma_create_qp(struct ib_qp *ibqp,
 
 		err_code = ib_respond_udata(udata, uresp);
 		if (err_code) {
-			irdma_destroy_qp(&iwqp->ibqp, udata);
+			_irdma_destroy_qp(&iwqp->ibqp);
 			return err_code;
 		}
 	}
@@ -1981,6 +2005,11 @@ static int irdma_destroy_srq(struct ib_srq *ibsrq, struct ib_udata *udata)
 	struct irdma_device *iwdev = to_iwdev(ibsrq->device);
 	struct irdma_srq *iwsrq = to_iwsrq(ibsrq);
 	struct irdma_sc_srq *srq = &iwsrq->sc_srq;
+	int ret;
+
+	ret = ib_no_udata_io(udata);
+	if (ret)
+		return ret;
 
 	irdma_srq_wq_destroy(iwdev->rf, srq);
 	irdma_srq_free_rsrc(iwdev->rf, iwsrq);
@@ -2001,6 +2030,11 @@ static int irdma_destroy_cq(struct ib_cq *ib_cq, struct ib_udata *udata)
 	struct irdma_sc_ceq *ceq = dev->ceq[cq->ceq_id];
 	struct irdma_ceq *iwceq = container_of(ceq, struct irdma_ceq, sc_ceq);
 	unsigned long flags;
+	int ret;
+
+	ret = ib_no_udata_io(udata);
+	if (ret)
+		return ret;
 
 	spin_lock_irqsave(&iwcq->lock, flags);
 	if (!list_empty(&iwcq->cmpl_generated))
@@ -2235,6 +2269,10 @@ static int irdma_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
 	struct cqp_cmds_info *cqp_info;
 	int status;
 
+	status = ib_no_udata_io(udata);
+	if (status)
+		return status;
+
 	if (attr_mask & IB_SRQ_MAX_WR)
 		return -EINVAL;
 
@@ -3080,6 +3118,10 @@ static int irdma_alloc_mw(struct ib_mw *ibmw, struct ib_udata *udata)
 	int err_code;
 	u32 stag;
 
+	err_code = ib_no_udata_io(udata);
+	if (err_code)
+		return err_code;
+
 	stag = irdma_create_stag(iwdev);
 	if (!stag)
 		return -ENOMEM;
@@ -3831,6 +3873,10 @@ static struct ib_mr *irdma_rereg_user_mr(struct ib_mr *ib_mr, int flags,
 	struct ib_umem_dmabuf *umem_dmabuf;
 	int ret;
 
+	ret = ib_no_udata_io(udata);
+	if (ret)
+		return ERR_PTR(ret);
+
 	if (len > iwdev->rf->sc_dev.hw_attrs.max_mr_size)
 		return ERR_PTR(-EINVAL);
 
@@ -4026,6 +4072,10 @@ static int irdma_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata)
 	bool dmabuf_revocable = iwmr->region && iwmr->region->is_dmabuf;
 	int ret;
 
+	ret = ib_no_udata_io(udata);
+	if (ret)
+		return ret;
+
 	if (iwmr->type != IRDMA_MEMREG_TYPE_MEM) {
 		if (iwmr->region) {
 			struct irdma_ucontext *ucontext;
@@ -5347,6 +5397,10 @@ static int irdma_create_user_ah(struct ib_ah *ibah,
 	struct irdma_ah *parent_ah;
 	int err;
 
+	err = ib_is_udata_in_empty(udata);
+	if (err)
+		return err;
+
 	if (udata->outlen < IRDMA_CREATE_AH_MIN_RESP_LEN)
 		return -EINVAL;
 
@@ -5398,6 +5452,10 @@ static int irdma_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *attr,
 	struct irdma_device *iwdev = to_iwdev(ibah->pd->device);
 	int err;
 
+	err = ib_no_udata_io(udata);
+	if (err)
+		return err;
+
 	err = irdma_setup_ah(ibah, attr);
 	if (err)
 		return err;
-- 
2.55.0.rc0.799.gd6f94ed593-goog


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH rdma-next v3 3/7] RDMA/irdma: Clear udata response buffers where necessary
  2026-07-02 17:06 [PATCH rdma-next v3 0/7] RDMA/irdma: Adopt robust udata Jacob Moroni
  2026-07-02 17:06 ` [PATCH rdma-next v3 1/7] RDMA/core: Add ib_no_udata_io() helper Jacob Moroni
  2026-07-02 17:06 ` [PATCH rdma-next v3 2/7] RDMA/irdma: Add checks for no udata Jacob Moroni
@ 2026-07-02 17:06 ` Jacob Moroni
  2026-07-02 17:06 ` [PATCH rdma-next v3 4/7] RDMA/irdma: Use robust input copy helpers Jacob Moroni
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Jacob Moroni @ 2026-07-02 17:06 UTC (permalink / raw)
  To: tatyana.e.nikolova, jgg, leon; +Cc: linux-rdma, Jacob Moroni

Methods that may accept udata input but do not provide a
udata response should use the ib_respond_empty_udata()
helper to ensure that user response buffers are cleared.

Since the ib_respond_empty_udata() call itself can fail if
the user intentionally provides a bogus output buffer, it is
called at the beginning of the method to fail early before
mutating any state that would be difficult to unwind.

Additionally, add missing bounds validation for udata->outlen
in irdma_create_srq() to ensure it is large enough to hold the
response struct as per its original (and so far, only) definition.

Signed-off-by: Jacob Moroni <jmoroni@google.com>
---
 drivers/infiniband/hw/irdma/verbs.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index be964f777e64..d5795d4fe7b3 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -1316,6 +1316,11 @@ int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 	u8 issue_modify_qp = 0;
 	int ret = 0;
 
+	/* Clear the response buffer (if any). It may be updated again later. */
+	ret = ib_respond_empty_udata(udata);
+	if (ret)
+		return ret;
+
 	ctx_info = &iwqp->ctx_info;
 	roce_info = &iwqp->roce_info;
 	udp_info = &iwqp->udp_info;
@@ -1676,6 +1681,10 @@ int irdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
 	int err;
 	unsigned long flags;
 
+	err = ib_respond_empty_udata(udata);
+	if (err)
+		return err;
+
 	if (udata) {
 		/* udata inlen/outlen can be 0 when supporting legacy libi40iw */
 		if ((udata->inlen && udata->inlen < IRDMA_MODIFY_QP_MIN_REQ_LEN) ||
@@ -2095,6 +2104,10 @@ static int irdma_resize_cq(struct ib_cq *ibcq, unsigned int entries,
 	if (entries > rf->max_cqe)
 		return -EINVAL;
 
+	ret = ib_respond_empty_udata(udata);
+	if (ret)
+		return ret;
+
 	if (!iwcq->user_mode) {
 		entries += 2;
 
@@ -2395,6 +2408,7 @@ static int irdma_create_srq(struct ib_srq *ibsrq,
 			    struct ib_srq_init_attr *initattrs,
 			    struct ib_udata *udata)
 {
+#define IRDMA_CREATE_SRQ_MIN_RESP_LEN offsetofend(struct irdma_create_srq_resp, srq_size)
 	struct irdma_device *iwdev = to_iwdev(ibsrq->device);
 	struct ib_srq_attr *attr = &initattrs->attr;
 	struct irdma_pd *iwpd = to_iwpd(ibsrq->pd);
@@ -2415,6 +2429,9 @@ static int irdma_create_srq(struct ib_srq *ibsrq,
 	if (initattrs->srq_type != IB_SRQT_BASIC)
 		return -EOPNOTSUPP;
 
+	if (udata && udata->outlen < IRDMA_CREATE_SRQ_MIN_RESP_LEN)
+		return -EINVAL;
+
 	if (!(uk_attrs->feature_flags & IRDMA_FEATURE_SRQ) ||
 	    attr->max_sge > uk_attrs->max_hw_wq_frags)
 		return -EINVAL;
@@ -3607,6 +3624,10 @@ static struct ib_mr *irdma_reg_user_mr(struct ib_pd *pd, u64 start, u64 len,
 	if (dmah)
 		return ERR_PTR(-EOPNOTSUPP);
 
+	err = ib_respond_empty_udata(udata);
+	if (err)
+		return ERR_PTR(err);
+
 	if (len > iwdev->rf->sc_dev.hw_attrs.max_mr_size)
 		return ERR_PTR(-EINVAL);
 
-- 
2.55.0.rc0.799.gd6f94ed593-goog


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH rdma-next v3 4/7] RDMA/irdma: Use robust input copy helpers
  2026-07-02 17:06 [PATCH rdma-next v3 0/7] RDMA/irdma: Adopt robust udata Jacob Moroni
                   ` (2 preceding siblings ...)
  2026-07-02 17:06 ` [PATCH rdma-next v3 3/7] RDMA/irdma: Clear udata response buffers where necessary Jacob Moroni
@ 2026-07-02 17:06 ` Jacob Moroni
  2026-07-02 17:06 ` [PATCH rdma-next v3 5/7] RDMA/irdma: Use robust udata helper for QP creation Jacob Moroni
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Jacob Moroni @ 2026-07-02 17:06 UTC (permalink / raw)
  To: tatyana.e.nikolova, jgg, leon; +Cc: linux-rdma, Jacob Moroni

Replace the use of ib_copy_from_udata() with
ib_copy_validate_udata_in() where applicable.

For each modified call site, the last argument of
ib_copy_validate_udata_in() was determined by taking
the last member of the ABI struct as per its original
definition (i.e., when it was first committed).

Some methods like irdma_create_cq required special care
because the last member of the current ABI def is beyond
that of the legacy i40iw's ABI def which we need to
remain compatible with. In some other cases like modify_qp,
the legacy i40iw provider never provided any udata at all
so the validation is only performed if inlen > 0.

irdma_create_qp is more challenging because the legacy ABI
was actually larger but the additional fields were never used,
and even worse, never initialized in the provider. This will
be handled in a followup commit.

Signed-off-by: Jacob Moroni <jmoroni@google.com>
---
 drivers/infiniband/hw/irdma/verbs.c | 79 +++++++++++++----------------
 1 file changed, 34 insertions(+), 45 deletions(-)

diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index d5795d4fe7b3..519ac780e9f1 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -1300,7 +1300,6 @@ static int irdma_wait_for_suspend(struct irdma_qp *iwqp)
 int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 			 int attr_mask, struct ib_udata *udata)
 {
-#define IRDMA_MODIFY_QP_MIN_REQ_LEN offsetofend(struct irdma_modify_qp_req, rq_flush)
 #define IRDMA_MODIFY_QP_MIN_RESP_LEN offsetofend(struct irdma_modify_qp_resp, push_valid)
 	struct irdma_pd *iwpd = to_iwpd(ibqp->pd);
 	struct irdma_qp *iwqp = to_iwqp(ibqp);
@@ -1327,9 +1326,15 @@ int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 
 	if (udata) {
 		/* udata inlen/outlen can be 0 when supporting legacy libi40iw */
-		if ((udata->inlen && udata->inlen < IRDMA_MODIFY_QP_MIN_REQ_LEN) ||
-		    (udata->outlen && udata->outlen < IRDMA_MODIFY_QP_MIN_RESP_LEN))
+		if (udata->outlen && udata->outlen < IRDMA_MODIFY_QP_MIN_RESP_LEN)
 			return -EINVAL;
+
+		/* For current irdma, validate against ABI def. */
+		if (udata->inlen) {
+			ret = ib_copy_validate_udata_in(udata, ureq, rsvd);
+			if (ret)
+				return ret;
+		}
 	}
 
 	if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
@@ -1572,10 +1577,6 @@ int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 				iwqp->ibqp_state = attr->qp_state;
 				spin_unlock_irqrestore(&iwqp->lock, flags);
 				if (udata && udata->inlen) {
-					if (ib_copy_from_udata(&ureq, udata,
-					    min(sizeof(ureq), udata->inlen)))
-						return -EINVAL;
-
 					irdma_flush_wqes(iwqp,
 					    (ureq.sq_flush ? IRDMA_FLUSH_SQ : 0) |
 					    (ureq.rq_flush ? IRDMA_FLUSH_RQ : 0) |
@@ -1665,7 +1666,6 @@ int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 int irdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
 		    struct ib_udata *udata)
 {
-#define IRDMA_MODIFY_QP_MIN_REQ_LEN offsetofend(struct irdma_modify_qp_req, rq_flush)
 #define IRDMA_MODIFY_QP_MIN_RESP_LEN offsetofend(struct irdma_modify_qp_resp, push_valid)
 	struct irdma_qp *iwqp = to_iwqp(ibqp);
 	struct irdma_device *iwdev = iwqp->iwdev;
@@ -1687,9 +1687,14 @@ int irdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
 
 	if (udata) {
 		/* udata inlen/outlen can be 0 when supporting legacy libi40iw */
-		if ((udata->inlen && udata->inlen < IRDMA_MODIFY_QP_MIN_REQ_LEN) ||
-		    (udata->outlen && udata->outlen < IRDMA_MODIFY_QP_MIN_RESP_LEN))
+		if (udata->outlen && udata->outlen < IRDMA_MODIFY_QP_MIN_RESP_LEN)
 			return -EINVAL;
+
+		if (udata->inlen) {
+			err = ib_copy_validate_udata_in(udata, ureq, rsvd);
+			if (err)
+				return err;
+		}
 	}
 
 	if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS)
@@ -1779,10 +1784,6 @@ int irdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
 				iwqp->ibqp_state = attr->qp_state;
 				spin_unlock_irqrestore(&iwqp->lock, flags);
 				if (udata && udata->inlen) {
-					if (ib_copy_from_udata(&ureq, udata,
-					    min(sizeof(ureq), udata->inlen)))
-						return -EINVAL;
-
 					irdma_flush_wqes(iwqp,
 					    (ureq.sq_flush ? IRDMA_FLUSH_SQ : 0) |
 					    (ureq.rq_flush ? IRDMA_FLUSH_RQ : 0) |
@@ -2074,7 +2075,6 @@ static int irdma_destroy_cq(struct ib_cq *ib_cq, struct ib_udata *udata)
 static int irdma_resize_cq(struct ib_cq *ibcq, unsigned int entries,
 			   struct ib_udata *udata)
 {
-#define IRDMA_RESIZE_CQ_MIN_REQ_LEN offsetofend(struct irdma_resize_cq_req, user_cq_buffer)
 	struct irdma_cq *iwcq = to_iwcq(ibcq);
 	struct irdma_sc_dev *dev = iwcq->sc_cq.dev;
 	struct irdma_cqp_request *cqp_request;
@@ -2098,9 +2098,6 @@ static int irdma_resize_cq(struct ib_cq *ibcq, unsigned int entries,
 	    IRDMA_FEATURE_CQ_RESIZE))
 		return -EOPNOTSUPP;
 
-	if (udata && udata->inlen < IRDMA_RESIZE_CQ_MIN_REQ_LEN)
-		return -EINVAL;
-
 	if (entries > rf->max_cqe)
 		return -EINVAL;
 
@@ -2134,9 +2131,9 @@ static int irdma_resize_cq(struct ib_cq *ibcq, unsigned int entries,
 			rdma_udata_to_drv_context(udata, struct irdma_ucontext,
 						  ibucontext);
 
-		if (ib_copy_from_udata(&req, udata,
-				       min(sizeof(req), udata->inlen)))
-			return -EINVAL;
+		ret = ib_copy_validate_udata_in(udata, req, user_cq_buffer);
+		if (ret)
+			return ret;
 
 		spin_lock_irqsave(&ucontext->cq_reg_mem_list_lock, flags);
 		iwpbl_buf = irdma_get_pbl((unsigned long)req.user_cq_buffer,
@@ -2328,24 +2325,20 @@ static int irdma_setup_umode_srq(struct irdma_device *iwdev,
 				 struct irdma_srq_init_info *info,
 				 struct ib_udata *udata)
 {
-#define IRDMA_CREATE_SRQ_MIN_REQ_LEN \
-	offsetofend(struct irdma_create_srq_req, user_shadow_area)
 	struct irdma_create_srq_req req = {};
 	struct irdma_ucontext *ucontext;
 	struct irdma_srq_mr *srqmr;
 	struct irdma_pbl *iwpbl;
 	unsigned long flags;
+	int ret;
 
 	iwsrq->user_mode = true;
 	ucontext = rdma_udata_to_drv_context(udata, struct irdma_ucontext,
 					     ibucontext);
 
-	if (udata->inlen < IRDMA_CREATE_SRQ_MIN_REQ_LEN)
-		return -EINVAL;
-
-	if (ib_copy_from_udata(&req, udata,
-			       min(sizeof(req), udata->inlen)))
-		return -EFAULT;
+	ret = ib_copy_validate_udata_in(udata, req, user_shadow_area);
+	if (ret)
+		return ret;
 
 	spin_lock_irqsave(&ucontext->srq_reg_mem_list_lock, flags);
 	iwpbl = irdma_get_pbl((unsigned long)req.user_srq_buf,
@@ -2559,7 +2552,6 @@ static int irdma_create_cq(struct ib_cq *ibcq,
 			   const struct ib_cq_init_attr *attr,
 			   struct uverbs_attr_bundle *attrs)
 {
-#define IRDMA_CREATE_CQ_MIN_REQ_LEN offsetofend(struct irdma_create_cq_req, user_cq_buf)
 #define IRDMA_CREATE_CQ_MIN_RESP_LEN offsetofend(struct irdma_create_cq_resp, cq_size)
 	struct ib_udata *udata = &attrs->driver_udata;
 	struct ib_device *ibdev = ibcq->device;
@@ -2583,8 +2575,7 @@ static int irdma_create_cq(struct ib_cq *ibcq,
 	if (err_code)
 		return err_code;
 
-	if (udata && (udata->inlen < IRDMA_CREATE_CQ_MIN_REQ_LEN ||
-		      udata->outlen < IRDMA_CREATE_CQ_MIN_RESP_LEN))
+	if (udata && udata->outlen < IRDMA_CREATE_CQ_MIN_RESP_LEN)
 		return -EINVAL;
 
 	err_code = irdma_alloc_rsrc(rf, rf->allocated_cqs, rf->max_cq, &cq_num,
@@ -2626,11 +2617,14 @@ static int irdma_create_cq(struct ib_cq *ibcq,
 		ucontext =
 			rdma_udata_to_drv_context(udata, struct irdma_ucontext,
 						  ibucontext);
-		if (ib_copy_from_udata(&req, udata,
-				       min(sizeof(req), udata->inlen))) {
-			err_code = -EFAULT;
+		/* Even though the last member of struct irdma_create_cq_req
+		 * was always user_shadow_area, we need backwards compat with
+		 * the legacy i40iw struct i40iw_ucreate_cq which stopped
+		 * at user_cq_buffer.
+		 */
+		err_code = ib_copy_validate_udata_in(udata, req, user_cq_buf);
+		if (err_code)
 			goto cq_free_rsrc;
-		}
 
 		spin_lock_irqsave(&ucontext->cq_reg_mem_list_lock, flags);
 		iwcq->iwpbl = irdma_get_pbl((unsigned long)req.user_cq_buf,
@@ -3614,7 +3608,6 @@ static struct ib_mr *irdma_reg_user_mr(struct ib_pd *pd, u64 start, u64 len,
 				       struct ib_dmah *dmah,
 				       struct ib_udata *udata)
 {
-#define IRDMA_MEM_REG_MIN_REQ_LEN offsetofend(struct irdma_mem_reg_req, sq_pages)
 	struct irdma_device *iwdev = to_iwdev(pd->device);
 	struct irdma_mem_reg_req req = {};
 	struct ib_umem *region = NULL;
@@ -3624,6 +3617,10 @@ static struct ib_mr *irdma_reg_user_mr(struct ib_pd *pd, u64 start, u64 len,
 	if (dmah)
 		return ERR_PTR(-EOPNOTSUPP);
 
+	err = ib_copy_validate_udata_in(udata, req, sq_pages);
+	if (err)
+		return ERR_PTR(err);
+
 	err = ib_respond_empty_udata(udata);
 	if (err)
 		return ERR_PTR(err);
@@ -3631,9 +3628,6 @@ static struct ib_mr *irdma_reg_user_mr(struct ib_pd *pd, u64 start, u64 len,
 	if (len > iwdev->rf->sc_dev.hw_attrs.max_mr_size)
 		return ERR_PTR(-EINVAL);
 
-	if (udata->inlen < IRDMA_MEM_REG_MIN_REQ_LEN)
-		return ERR_PTR(-EINVAL);
-
 	region = ib_umem_get_va(pd->device, start, len, access);
 
 	if (IS_ERR(region)) {
@@ -3642,11 +3636,6 @@ static struct ib_mr *irdma_reg_user_mr(struct ib_pd *pd, u64 start, u64 len,
 		return (struct ib_mr *)region;
 	}
 
-	if (ib_copy_from_udata(&req, udata, min(sizeof(req), udata->inlen))) {
-		ib_umem_release(region);
-		return ERR_PTR(-EFAULT);
-	}
-
 	iwmr = irdma_alloc_iwmr(region, pd, virt, req.reg_type);
 	if (IS_ERR(iwmr)) {
 		ib_umem_release(region);
-- 
2.55.0.rc0.799.gd6f94ed593-goog


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH rdma-next v3 5/7] RDMA/irdma: Use robust udata helper for QP creation
  2026-07-02 17:06 [PATCH rdma-next v3 0/7] RDMA/irdma: Adopt robust udata Jacob Moroni
                   ` (3 preceding siblings ...)
  2026-07-02 17:06 ` [PATCH rdma-next v3 4/7] RDMA/irdma: Use robust input copy helpers Jacob Moroni
@ 2026-07-02 17:06 ` Jacob Moroni
  2026-07-12  8:29   ` Leon Romanovsky
  2026-07-02 17:06 ` [PATCH rdma-next v3 6/7] RDMA/irdma: Fix legacy i40iw compat check in create_qp Jacob Moroni
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 11+ messages in thread
From: Jacob Moroni @ 2026-07-02 17:06 UTC (permalink / raw)
  To: tatyana.e.nikolova, jgg, leon; +Cc: linux-rdma, Jacob Moroni

Replace the manual udata input copy and validation during
QP creation with the robust helper.

The irdma driver is backwards compatible with the legacy
i40iw userspace provider. The current create_qp ABI contains
two 8 byte fields. The legacy i40iw ABI was the same but
also contained two additional fields which were never actually
used. Furthermore, the i40iw userspace provider never explicitly
zero-initialized those extra fields, so there is a chance that
existing binaries are passing non-zero garbage values down
to the kernel.

Previously, the irdma driver only copied out the first 16
bytes and did not have any check for the rest of the buffer
being zero, so that additional garbage didn't matter.

By switching to ib_copy_validate_udata_in(), we will now be
checking to ensure that data beyond the kernel's definition
of the request is all zero.

In order to avoid breaking legacy binaries, we therefore need
to increase the request structure size to cover those garbage
fields.

- Legacy binaries will continue to pass down a 32 byte request,
  with the driver copying the entire 32 bytes out but ignoring
  the second 16 bytes, just as before.

- Newer binaries will pass down the normal 16 byte request. The
  ib_copy_validate_udata_in() call will allow this to succeed
  because we use user_compl_ctx as our minimum length (16 bytes).

- If the request is ever extended, the new fields would be
  added after the "don't use" fields and would work as per
  the normal uAPI mechanism.

Signed-off-by: Jacob Moroni <jmoroni@google.com>
---
 drivers/infiniband/hw/irdma/verbs.c | 41 ++++++++++++++++-------------
 include/uapi/rdma/irdma-abi.h       |  1 +
 2 files changed, 23 insertions(+), 19 deletions(-)

diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index 519ac780e9f1..00a648922c7b 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -632,37 +632,29 @@ static void irdma_setup_virt_qp(struct irdma_device *iwdev,
 
 /**
  * irdma_setup_umode_qp - setup sq and rq size in user mode qp
- * @udata: udata
+ * @ucontext: user context
+ * @req: user request pointer
  * @iwdev: iwarp device
  * @iwqp: qp ptr (user or kernel)
  * @info: initialize info to return
  * @init_attr: Initial QP create attributes
  */
-static int irdma_setup_umode_qp(struct ib_udata *udata,
+static int irdma_setup_umode_qp(struct irdma_ucontext *ucontext,
+				struct irdma_create_qp_req *req,
 				struct irdma_device *iwdev,
 				struct irdma_qp *iwqp,
 				struct irdma_qp_init_info *info,
 				struct ib_qp_init_attr *init_attr)
 {
-	struct irdma_ucontext *ucontext = rdma_udata_to_drv_context(udata,
-				struct irdma_ucontext, ibucontext);
 	struct irdma_qp_uk_init_info *ukinfo = &info->qp_uk_init_info;
-	struct irdma_create_qp_req req;
 	unsigned long flags;
 	int ret;
 
-	ret = ib_copy_from_udata(&req, udata,
-				 min(sizeof(req), udata->inlen));
-	if (ret) {
-		ibdev_dbg(&iwdev->ibdev, "VERBS: ib_copy_from_data fail\n");
-		return ret;
-	}
-
-	iwqp->ctx_info.qp_compl_ctx = req.user_compl_ctx;
+	iwqp->ctx_info.qp_compl_ctx = req->user_compl_ctx;
 	iwqp->user_mode = 1;
 
 	spin_lock_irqsave(&ucontext->qp_reg_mem_list_lock, flags);
-	iwqp->iwpbl = irdma_get_pbl((unsigned long)req.user_wqe_bufs,
+	iwqp->iwpbl = irdma_get_pbl((unsigned long)req->user_wqe_bufs,
 				    &ucontext->qp_reg_mem_list);
 	spin_unlock_irqrestore(&ucontext->qp_reg_mem_list_lock, flags);
 
@@ -989,6 +981,7 @@ static int irdma_create_qp(struct ib_qp *ibqp,
 	struct irdma_uk_attrs *uk_attrs = &dev->hw_attrs.uk_attrs;
 	struct irdma_qp_init_info init_info = {};
 	struct irdma_qp_host_ctx_info *ctx_info;
+	struct irdma_create_qp_req ureq = {};
 	struct irdma_srq *iwsrq;
 	bool srq_valid = false;
 	u32 srq_id = 0;
@@ -1006,9 +999,14 @@ static int irdma_create_qp(struct ib_qp *ibqp,
 	if (err_code)
 		return err_code;
 
-	if (udata && (udata->inlen < IRDMA_CREATE_QP_MIN_REQ_LEN ||
-		      udata->outlen < IRDMA_CREATE_QP_MIN_RESP_LEN))
-		return -EINVAL;
+	if (udata) {
+		if (udata->outlen < IRDMA_CREATE_QP_MIN_RESP_LEN)
+			return -EINVAL;
+
+		err_code = ib_copy_validate_udata_in(udata, ureq, user_compl_ctx);
+		if (err_code)
+			return err_code;
+	}
 
 	init_info.vsi = &iwdev->vsi;
 	init_info.qp_uk_init_info.uk_attrs = uk_attrs;
@@ -1067,9 +1065,14 @@ static int irdma_create_qp(struct ib_qp *ibqp,
 	init_waitqueue_head(&iwqp->mod_qp_waitq);
 
 	if (udata) {
+		struct irdma_ucontext *ucontext =
+			rdma_udata_to_drv_context(udata,
+						  struct irdma_ucontext,
+						  ibucontext);
+
 		init_info.qp_uk_init_info.abi_ver = iwpd->sc_pd.abi_ver;
-		err_code = irdma_setup_umode_qp(udata, iwdev, iwqp, &init_info,
-						init_attr);
+		err_code = irdma_setup_umode_qp(ucontext, &ureq, iwdev, iwqp,
+						&init_info, init_attr);
 	} else {
 		INIT_DELAYED_WORK(&iwqp->dwork_flush, irdma_flush_worker);
 		init_info.qp_uk_init_info.abi_ver = IRDMA_ABI_VER;
diff --git a/include/uapi/rdma/irdma-abi.h b/include/uapi/rdma/irdma-abi.h
index 36f20802bcc8..38155affc8b4 100644
--- a/include/uapi/rdma/irdma-abi.h
+++ b/include/uapi/rdma/irdma-abi.h
@@ -88,6 +88,7 @@ struct irdma_create_srq_resp {
 struct irdma_create_qp_req {
 	__aligned_u64 user_wqe_bufs;
 	__aligned_u64 user_compl_ctx;
+	__aligned_u64 legacy_dontuse[2];
 };
 
 struct irdma_mem_reg_req {
-- 
2.55.0.rc0.799.gd6f94ed593-goog


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH rdma-next v3 6/7] RDMA/irdma: Fix legacy i40iw compat check in create_qp
  2026-07-02 17:06 [PATCH rdma-next v3 0/7] RDMA/irdma: Adopt robust udata Jacob Moroni
                   ` (4 preceding siblings ...)
  2026-07-02 17:06 ` [PATCH rdma-next v3 5/7] RDMA/irdma: Use robust udata helper for QP creation Jacob Moroni
@ 2026-07-02 17:06 ` Jacob Moroni
  2026-07-02 17:06 ` [PATCH rdma-next v3 7/7] RDMA/irdma: Enable uverbs_robust_udata compliance flag Jacob Moroni
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Jacob Moroni @ 2026-07-02 17:06 UTC (permalink / raw)
  To: tatyana.e.nikolova, jgg, leon; +Cc: linux-rdma, Jacob Moroni

The irdma driver maintains backward compatibility with the
legacy i40iw userspace provider by checking the length of
the user response buffer in irdma_create_qp.

Previously, the check relied on udata->outlen < sizeof(uresp).
That is technically okay since there have only ever been two
sizes for the resp struct (legacy and current). However, it
would be a problem if the resp struct is ever expanded in
the future because it would end up triggering the legacy
fallback path for non-legacy irdma providers that just  haven't
moved over to the newer expanded struct yet.

Fix this by explicitly checking for the exact legacy resp size.

Signed-off-by: Jacob Moroni <jmoroni@google.com>
---
 drivers/infiniband/hw/irdma/verbs.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index 00a648922c7b..d8374f7afa87 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -1139,8 +1139,12 @@ static int irdma_create_qp(struct ib_qp *ibqp,
 	init_completion(&iwqp->free_qp);
 
 	if (udata) {
-		/* GEN_1 legacy support with libi40iw does not have expanded uresp struct */
-		if (udata->outlen < sizeof(uresp)) {
+		/* GEN_1 legacy support with libi40iw does not have expanded
+		 * uresp struct. Check for the exact legacy size (20 bytes) to
+		 * ensure that newer expanded uresp structs don't accidentally
+		 * trigger the legacy fallback.
+		 */
+		if (udata->outlen == IRDMA_CREATE_QP_MIN_RESP_LEN) {
 			uresp.lsmm = 1;
 			uresp.push_idx = IRDMA_INVALID_PUSH_PAGE_INDEX_GEN_1;
 		} else {
-- 
2.55.0.rc0.799.gd6f94ed593-goog


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH rdma-next v3 7/7] RDMA/irdma: Enable uverbs_robust_udata compliance flag
  2026-07-02 17:06 [PATCH rdma-next v3 0/7] RDMA/irdma: Adopt robust udata Jacob Moroni
                   ` (5 preceding siblings ...)
  2026-07-02 17:06 ` [PATCH rdma-next v3 6/7] RDMA/irdma: Fix legacy i40iw compat check in create_qp Jacob Moroni
@ 2026-07-02 17:06 ` Jacob Moroni
  2026-07-12  8:31 ` (subset) [PATCH rdma-next v3 0/7] RDMA/irdma: Adopt robust udata Leon Romanovsky
  2026-07-12  8:32 ` Leon Romanovsky
  8 siblings, 0 replies; 11+ messages in thread
From: Jacob Moroni @ 2026-07-02 17:06 UTC (permalink / raw)
  To: tatyana.e.nikolova, jgg, leon; +Cc: linux-rdma, Jacob Moroni

The irdma driver has been audited to confirm that:

1. Methods which do not accept udata input perform an explicit
   check for no (or zero value) input.
2. Methods which do accept input perform the correct validation
   to ensure that additional udata beyond the kernel's current
   ABI definition is zero, and to enforce the required minimum
   length.
3. Methods which do not return udata responses use the proper
   helper.

Signed-off-by: Jacob Moroni <jmoroni@google.com>
---
 drivers/infiniband/hw/irdma/verbs.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index d8374f7afa87..99742e7c81f3 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -5555,6 +5555,7 @@ static const struct ib_device_ops irdma_dev_ops = {
 	.owner = THIS_MODULE,
 	.driver_id = RDMA_DRIVER_IRDMA,
 	.uverbs_abi_ver = IRDMA_ABI_VER,
+	.uverbs_robust_udata = 1,
 
 	.alloc_hw_port_stats = irdma_alloc_hw_port_stats,
 	.alloc_mr = irdma_alloc_mr,
-- 
2.55.0.rc0.799.gd6f94ed593-goog


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH rdma-next v3 5/7] RDMA/irdma: Use robust udata helper for QP creation
  2026-07-02 17:06 ` [PATCH rdma-next v3 5/7] RDMA/irdma: Use robust udata helper for QP creation Jacob Moroni
@ 2026-07-12  8:29   ` Leon Romanovsky
  0 siblings, 0 replies; 11+ messages in thread
From: Leon Romanovsky @ 2026-07-12  8:29 UTC (permalink / raw)
  To: Jacob Moroni; +Cc: tatyana.e.nikolova, jgg, linux-rdma

On Thu, Jul 02, 2026 at 05:06:50PM +0000, Jacob Moroni wrote:
> Replace the manual udata input copy and validation during
> QP creation with the robust helper.
> 
> The irdma driver is backwards compatible with the legacy
> i40iw userspace provider. The current create_qp ABI contains
> two 8 byte fields. The legacy i40iw ABI was the same but
> also contained two additional fields which were never actually
> used. Furthermore, the i40iw userspace provider never explicitly
> zero-initialized those extra fields, so there is a chance that
> existing binaries are passing non-zero garbage values down
> to the kernel.
> 
> Previously, the irdma driver only copied out the first 16
> bytes and did not have any check for the rest of the buffer
> being zero, so that additional garbage didn't matter.
> 
> By switching to ib_copy_validate_udata_in(), we will now be
> checking to ensure that data beyond the kernel's definition
> of the request is all zero.
> 
> In order to avoid breaking legacy binaries, we therefore need
> to increase the request structure size to cover those garbage
> fields.
> 
> - Legacy binaries will continue to pass down a 32 byte request,
>   with the driver copying the entire 32 bytes out but ignoring
>   the second 16 bytes, just as before.
> 
> - Newer binaries will pass down the normal 16 byte request. The
>   ib_copy_validate_udata_in() call will allow this to succeed
>   because we use user_compl_ctx as our minimum length (16 bytes).
> 
> - If the request is ever extended, the new fields would be
>   added after the "don't use" fields and would work as per
>   the normal uAPI mechanism.
> 
> Signed-off-by: Jacob Moroni <jmoroni@google.com>
> ---
>  drivers/infiniband/hw/irdma/verbs.c | 41 ++++++++++++++++-------------
>  include/uapi/rdma/irdma-abi.h       |  1 +
>  2 files changed, 23 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
> index 519ac780e9f1..00a648922c7b 100644
> --- a/drivers/infiniband/hw/irdma/verbs.c
> +++ b/drivers/infiniband/hw/irdma/verbs.c
> @@ -632,37 +632,29 @@ static void irdma_setup_virt_qp(struct irdma_device *iwdev,
>  
>  /**
>   * irdma_setup_umode_qp - setup sq and rq size in user mode qp
> - * @udata: udata
> + * @ucontext: user context
> + * @req: user request pointer
>   * @iwdev: iwarp device
>   * @iwqp: qp ptr (user or kernel)
>   * @info: initialize info to return
>   * @init_attr: Initial QP create attributes
>   */
> -static int irdma_setup_umode_qp(struct ib_udata *udata,
> +static int irdma_setup_umode_qp(struct irdma_ucontext *ucontext,
> +				struct irdma_create_qp_req *req,
>  				struct irdma_device *iwdev,
>  				struct irdma_qp *iwqp,
>  				struct irdma_qp_init_info *info,
>  				struct ib_qp_init_attr *init_attr)
>  {
> -	struct irdma_ucontext *ucontext = rdma_udata_to_drv_context(udata,
> -				struct irdma_ucontext, ibucontext);
>  	struct irdma_qp_uk_init_info *ukinfo = &info->qp_uk_init_info;
> -	struct irdma_create_qp_req req;
>  	unsigned long flags;
>  	int ret;
>  
> -	ret = ib_copy_from_udata(&req, udata,
> -				 min(sizeof(req), udata->inlen));
> -	if (ret) {
> -		ibdev_dbg(&iwdev->ibdev, "VERBS: ib_copy_from_data fail\n");
> -		return ret;
> -	}
> -
> -	iwqp->ctx_info.qp_compl_ctx = req.user_compl_ctx;
> +	iwqp->ctx_info.qp_compl_ctx = req->user_compl_ctx;
>  	iwqp->user_mode = 1;
>  
>  	spin_lock_irqsave(&ucontext->qp_reg_mem_list_lock, flags);
> -	iwqp->iwpbl = irdma_get_pbl((unsigned long)req.user_wqe_bufs,
> +	iwqp->iwpbl = irdma_get_pbl((unsigned long)req->user_wqe_bufs,
>  				    &ucontext->qp_reg_mem_list);
>  	spin_unlock_irqrestore(&ucontext->qp_reg_mem_list_lock, flags);

Which codebase did you use for this series?

That function differs from the current implementation, which has
remained unchanged since 2023:
https://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma.git/tree/drivers/infiniband/hw/irdma/verbs.c#n639

Thanks

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: (subset) [PATCH rdma-next v3 0/7] RDMA/irdma: Adopt robust udata
  2026-07-02 17:06 [PATCH rdma-next v3 0/7] RDMA/irdma: Adopt robust udata Jacob Moroni
                   ` (6 preceding siblings ...)
  2026-07-02 17:06 ` [PATCH rdma-next v3 7/7] RDMA/irdma: Enable uverbs_robust_udata compliance flag Jacob Moroni
@ 2026-07-12  8:31 ` Leon Romanovsky
  2026-07-12  8:32 ` Leon Romanovsky
  8 siblings, 0 replies; 11+ messages in thread
From: Leon Romanovsky @ 2026-07-12  8:31 UTC (permalink / raw)
  To: tatyana.e.nikolova, jgg, Jacob Moroni; +Cc: linux-rdma


On Thu, 02 Jul 2026 17:06:45 +0000, Jacob Moroni wrote:
> This series brings irdma up to uverbs_robust_udata compliance.
> 
> The driver has been audited to confirm that:
> 
>   1. Methods which do not accept udata input perform an explicit
>      check for no (or zero value) input.
> 
> [...]

Applied, thanks!

[1/7] RDMA/core: Add ib_no_udata_io() helper
      https://git.kernel.org/rdma/rdma/c/a833ce42d05624

Best regards,
-- 
Leon Romanovsky <leon@kernel.org>


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH rdma-next v3 0/7] RDMA/irdma: Adopt robust udata
  2026-07-02 17:06 [PATCH rdma-next v3 0/7] RDMA/irdma: Adopt robust udata Jacob Moroni
                   ` (7 preceding siblings ...)
  2026-07-12  8:31 ` (subset) [PATCH rdma-next v3 0/7] RDMA/irdma: Adopt robust udata Leon Romanovsky
@ 2026-07-12  8:32 ` Leon Romanovsky
  8 siblings, 0 replies; 11+ messages in thread
From: Leon Romanovsky @ 2026-07-12  8:32 UTC (permalink / raw)
  To: Jacob Moroni; +Cc: tatyana.e.nikolova, jgg, linux-rdma

On Thu, Jul 02, 2026 at 05:06:45PM +0000, Jacob Moroni wrote:
> This series brings irdma up to uverbs_robust_udata compliance.
> 
> The driver has been audited to confirm that:
> 
>   1. Methods which do not accept udata input perform an explicit
>      check for no (or zero value) input.
> 
>   2. Methods which do accept input perform the correct validation
>      to ensure that additional udata beyond the kernel's current
>      ABI definition is zero, and to enforce the required minimum
>      length.
> 
>   3. Methods which do not return udata responses use the proper
>      helper.
> 
> The irdma driver is backwards compatible with the legacy i40iw
> provider, so special care was taken to avoid breaking any legacy
> binaries, as there were some small differences in the ABI/semantics.
> 
> This has passed the rdma-unit-test suite using the normal irdma
> provider from upstream rdma-core.
> 
> NOTE: This series is based on a few irdma bug fix patches
>       which have not yet been merged:
> 
> - RDMA/irdma: Prevent user-triggered null deref on QP create
>   https://patchwork.kernel.org/project/linux-rdma/list/?series=1113053
>      
> - RDMA/irdma: Prevent premature deregistration of user ring MRs
>   https://patchwork.kernel.org/project/linux-rdma/list/?series=1113648
> 
> Changes in v3:
> * Add ib_no_udata_io helper to more easily handle the
>   common case of no input/no output ops.
> * Fixed regression in create_qp failure path caught by sashiko.
> * Rebased on top of previous posted irdma fixes.
> * Fixed an additional latent legacy compat bug in create_qp.
> * Added missing response buffer clearing for reg/rereg_user_mr.
> Changes in v2:
> * Fixed Sashiko findings:
>   - Moved ib_respond_empty_udata to beginning of most
>     methods to close gaps where it could previously
>     return 0 without calling ib_respond_empty_udata. This
>     also fixes issues where the ib_respond_empty_udata
>     call itself could fail, which may leave resources
>     in an inconsistent state (kernel believes object
>     is alive, but driver resources have been cleaned up).
>   - Moved input validation to beginning of modify_qp
>     methods to close gaps where the op could be invoked
>     with udata but without input checking.
>   - Fixed a QPN leak that could occur during QP create
>     by moving input validation earlier.
> 
> v2: https://lore.kernel.org/linux-rdma/20260629232532.2057423-1-jmoroni@google.com/
> v1: https://lore.kernel.org/linux-rdma/20260627025642.4064973-1-jmoroni@google.com/T/#t
> 
> Jacob Moroni (7):
>   RDMA/core: Add ib_no_udata_io() helper

I applied only first patch, rest needs to be resent.

Thanks

>   RDMA/irdma: Add checks for no udata
>   RDMA/irdma: Clear udata response buffers where necessary
>   RDMA/irdma: Use robust input copy helpers
>   RDMA/irdma: Use robust udata helper for QP creation
>   RDMA/irdma: Fix legacy i40iw compat check in create_qp
>   RDMA/irdma: Enable uverbs_robust_udata compliance flag
> 
>  drivers/infiniband/hw/irdma/verbs.c | 216 +++++++++++++++++++---------
>  include/rdma/uverbs_ioctl.h         |  20 +++
>  include/uapi/rdma/irdma-abi.h       |   1 +
>  3 files changed, 167 insertions(+), 70 deletions(-)
> 
> -- 
> 2.55.0.rc0.799.gd6f94ed593-goog
> 

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2026-07-12  8:32 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-02 17:06 [PATCH rdma-next v3 0/7] RDMA/irdma: Adopt robust udata Jacob Moroni
2026-07-02 17:06 ` [PATCH rdma-next v3 1/7] RDMA/core: Add ib_no_udata_io() helper Jacob Moroni
2026-07-02 17:06 ` [PATCH rdma-next v3 2/7] RDMA/irdma: Add checks for no udata Jacob Moroni
2026-07-02 17:06 ` [PATCH rdma-next v3 3/7] RDMA/irdma: Clear udata response buffers where necessary Jacob Moroni
2026-07-02 17:06 ` [PATCH rdma-next v3 4/7] RDMA/irdma: Use robust input copy helpers Jacob Moroni
2026-07-02 17:06 ` [PATCH rdma-next v3 5/7] RDMA/irdma: Use robust udata helper for QP creation Jacob Moroni
2026-07-12  8:29   ` Leon Romanovsky
2026-07-02 17:06 ` [PATCH rdma-next v3 6/7] RDMA/irdma: Fix legacy i40iw compat check in create_qp Jacob Moroni
2026-07-02 17:06 ` [PATCH rdma-next v3 7/7] RDMA/irdma: Enable uverbs_robust_udata compliance flag Jacob Moroni
2026-07-12  8:31 ` (subset) [PATCH rdma-next v3 0/7] RDMA/irdma: Adopt robust udata Leon Romanovsky
2026-07-12  8:32 ` Leon Romanovsky

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox