diff --git a/drivers/infiniband/core/rdma_core.c b/drivers/infiniband/core/rdma_core.c
index a63844ba841449..9e84ded6d3bee3 100644
--- a/drivers/infiniband/core/rdma_core.c
+++ b/drivers/infiniband/core/rdma_core.c
@@ -924,10 +924,7 @@ int uverbs_finalize_object(struct ib_uobject *uobj,
 		rdma_lookup_put_uobject(uobj, true);
 		break;
 	case UVERBS_ACCESS_DESTROY:
-		if (commit)
-			ret = rdma_remove_commit_uobject(uobj);
-		else
-			rdma_lookup_put_uobject(uobj, true);
+		rdma_lookup_put_uobject(uobj, true);
 		break;
 	case UVERBS_ACCESS_NEW:
 		if (commit)
diff --git a/drivers/infiniband/core/uverbs_ioctl.c b/drivers/infiniband/core/uverbs_ioctl.c
index db7a92ea5dbe87..613ed0f85900fd 100644
--- a/drivers/infiniband/core/uverbs_ioctl.c
+++ b/drivers/infiniband/core/uverbs_ioctl.c
@@ -51,6 +51,7 @@ static int uverbs_process_attr(struct ib_uverbs_file *ufile,
 			       u16 attr_id,
 			       const struct uverbs_attr_spec_hash *attr_spec_bucket,
 			       struct uverbs_attr_bundle_hash *attr_bundle_h,
+			       struct uverbs_obj_attr **destroy_attr,
 			       struct ib_uverbs_attr __user *uattr_ptr)
 {
 	const struct uverbs_attr_spec *spec;
@@ -148,6 +149,12 @@ static int uverbs_process_attr(struct ib_uverbs_file *ufile,
 		if (!object)
 			return -EINVAL;
 
+		/* specs are allowed to have only one destroy attribute */
+		WARN_ON(spec->u.obj.access == UVERBS_ACCESS_DESTROY &&
+			*destroy_attr);
+		if (spec->u.obj.access == UVERBS_ACCESS_DESTROY)
+			*destroy_attr = o_attr;
+
 		/*
 		 * The type of uattr->data is u64 for UVERBS_ATTR_TYPE_IDR and
 		 * s64 for UVERBS_ATTR_TYPE_FD. We can cast the u64 to s64
@@ -235,6 +242,7 @@ static int uverbs_uattrs_process(struct ib_uverbs_file *ufile,
 				 size_t num_uattrs,
 				 const struct uverbs_method_spec *method,
 				 struct uverbs_attr_bundle *attr_bundle,
+				 struct uverbs_obj_attr **destroy_attr,
 				 struct ib_uverbs_attr __user *uattr_ptr)
 {
 	size_t i;
@@ -268,7 +276,8 @@ static int uverbs_uattrs_process(struct ib_uverbs_file *ufile,
 		attr_spec_bucket = method->attr_buckets[ret];
 		ret = uverbs_process_attr(ufile, uattr, attr_id,
 					  attr_spec_bucket,
-					  &attr_bundle->hash[ret], uattr_ptr++);
+					  &attr_bundle->hash[ret], destroy_attr,
+					  uattr_ptr++);
 		if (ret) {
 			uverbs_finalize_attrs(attr_bundle,
 					      method->attr_buckets,
@@ -322,9 +331,11 @@ static int uverbs_handle_method(struct ib_uverbs_attr __user *uattr_ptr,
 	int ret;
 	int finalize_ret;
 	int num_given_buckets;
+	struct uverbs_obj_attr *destroy_attr = NULL;
 
-	num_given_buckets = uverbs_uattrs_process(
-		ufile, uattrs, num_uattrs, method_spec, attr_bundle, uattr_ptr);
+	num_given_buckets =
+		uverbs_uattrs_process(ufile, uattrs, num_uattrs, method_spec,
+				      attr_bundle, &destroy_attr, uattr_ptr);
 	if (num_given_buckets <= 0)
 		return -EINVAL;
 
@@ -333,7 +344,18 @@ static int uverbs_handle_method(struct ib_uverbs_attr __user *uattr_ptr,
 	if (ret)
 		goto cleanup;
 
+	/*
+	 * We destroy the HW object before invoking the handler, handlers do
+	 * not get to manipulate the HW objects.
+	 */
+	if (destroy_attr) {
+		ret = rdma_explicit_destroy(destroy_attr->uobject);
+		if (ret)
+			goto cleanup;
+	}
+
 	ret = method_spec->handler(ibdev, ufile, attr_bundle);
+
 cleanup:
 	finalize_ret = uverbs_finalize_attrs(attr_bundle,
 					     method_spec->attr_buckets,
diff --git a/drivers/infiniband/core/uverbs_std_types_cq.c b/drivers/infiniband/core/uverbs_std_types_cq.c
index c71305fc043332..32930880975e56 100644
--- a/drivers/infiniband/core/uverbs_std_types_cq.c
+++ b/drivers/infiniband/core/uverbs_std_types_cq.c
@@ -176,21 +176,12 @@ static int UVERBS_HANDLER(UVERBS_METHOD_CQ_DESTROY)(struct ib_device *ib_dev,
 {
 	struct ib_uobject *uobj =
 		uverbs_attr_get_uobject(attrs, UVERBS_ATTR_DESTROY_CQ_HANDLE);
-	struct ib_uverbs_destroy_cq_resp resp;
-	struct ib_ucq_object *obj;
-	int ret;
-
-	if (IS_ERR(uobj))
-		return PTR_ERR(uobj);
-
-	obj = container_of(uobj, struct ib_ucq_object, uobject);
-
-	ret = rdma_explicit_destroy(uobj);
-	if (ret)
-		return ret;
-
-	resp.comp_events_reported  = obj->comp_events_reported;
-	resp.async_events_reported = obj->async_events_reported;
+	struct ib_ucq_object *obj =
+		container_of(uobj, struct ib_ucq_object, uobject);
+	struct ib_uverbs_destroy_cq_resp resp = {
+		.comp_events_reported = obj->comp_events_reported,
+		.async_events_reported = obj->async_events_reported
+	};
 
 	return uverbs_copy_to(attrs, UVERBS_ATTR_DESTROY_CQ_RESP, &resp,
 			      sizeof(resp));
