Skip to content

Commit d739322

Browse files
committed
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma
Pull rdma fixes frfom Jason Gunthorpe: "Not much so far. We have the usual batch of bugs and two fixes to code merged this cycle: - Restore valgrind support for the ioctl verbs interface merged this window, and fix a missed error code on an error path from that conversion - A user reported crash on obsolete mthca hardware - pvrdma was using the wrong command opcode toward the hypervisor - NULL pointer crash regression when dumping rdma-cm over netlink - Be conservative about exposing the global rkey" * tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma: RDMA/uverbs: Mark ioctl responses with UVERBS_ATTR_F_VALID_OUTPUT RDMA/mthca: Clear QP objects during their allocation RDMA/vmw_pvrdma: Return the correct opcode when creating WR RDMA/cma: Add cm_id restrack resource based on kernel or user cm_id type RDMA/nldev: Don't expose unsafe global rkey to regular user RDMA/uverbs: Fix post send success return value in case of error
2 parents 1092a94 + d6f4a21 commit d739322

File tree

10 files changed

+109
-22
lines changed

10 files changed

+109
-22
lines changed

drivers/infiniband/core/cma.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,10 @@ static void _cma_attach_to_dev(struct rdma_id_private *id_priv,
494494
id_priv->id.route.addr.dev_addr.transport =
495495
rdma_node_get_transport(cma_dev->device->node_type);
496496
list_add_tail(&id_priv->list, &cma_dev->id_list);
497-
rdma_restrack_kadd(&id_priv->res);
497+
if (id_priv->res.kern_name)
498+
rdma_restrack_kadd(&id_priv->res);
499+
else
500+
rdma_restrack_uadd(&id_priv->res);
498501
}
499502

500503
static void cma_attach_to_dev(struct rdma_id_private *id_priv,

drivers/infiniband/core/nldev.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -584,10 +584,6 @@ static int fill_res_pd_entry(struct sk_buff *msg, struct netlink_callback *cb,
584584
if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_RES_USECNT,
585585
atomic_read(&pd->usecnt), RDMA_NLDEV_ATTR_PAD))
586586
goto err;
587-
if ((pd->flags & IB_PD_UNSAFE_GLOBAL_RKEY) &&
588-
nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY,
589-
pd->unsafe_global_rkey))
590-
goto err;
591587

592588
if (fill_res_name_pid(msg, res))
593589
goto err;

drivers/infiniband/core/rdma_core.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ int uverbs_finalize_object(struct ib_uobject *uobj,
106106
enum uverbs_obj_access access,
107107
bool commit);
108108

109+
int uverbs_output_written(const struct uverbs_attr_bundle *bundle, size_t idx);
110+
109111
void setup_ufile_idr_uobject(struct ib_uverbs_file *ufile);
110112
void release_ufile_idr_uobject(struct ib_uverbs_file *ufile);
111113

drivers/infiniband/core/uverbs_cmd.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ static int uverbs_response(struct uverbs_attr_bundle *attrs, const void *resp,
6060
{
6161
int ret;
6262

63+
if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_CORE_OUT))
64+
return uverbs_copy_to_struct_or_zero(
65+
attrs, UVERBS_ATTR_CORE_OUT, resp, resp_len);
66+
6367
if (copy_to_user(attrs->ucore.outbuf, resp,
6468
min(attrs->ucore.outlen, resp_len)))
6569
return -EFAULT;
@@ -1181,6 +1185,9 @@ static int ib_uverbs_poll_cq(struct uverbs_attr_bundle *attrs)
11811185
goto out_put;
11821186
}
11831187

1188+
if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_CORE_OUT))
1189+
ret = uverbs_output_written(attrs, UVERBS_ATTR_CORE_OUT);
1190+
11841191
ret = 0;
11851192

11861193
out_put:
@@ -2012,8 +2019,10 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs)
20122019
return -ENOMEM;
20132020

20142021
qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs);
2015-
if (!qp)
2022+
if (!qp) {
2023+
ret = -EINVAL;
20162024
goto out;
2025+
}
20172026

20182027
is_ud = qp->qp_type == IB_QPT_UD;
20192028
sg_ind = 0;

drivers/infiniband/core/uverbs_ioctl.c

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,21 @@ static bool uverbs_is_attr_cleared(const struct ib_uverbs_attr *uattr,
144144
0, uattr->len - len);
145145
}
146146

147+
static int uverbs_set_output(const struct uverbs_attr_bundle *bundle,
148+
const struct uverbs_attr *attr)
149+
{
150+
struct bundle_priv *pbundle =
151+
container_of(bundle, struct bundle_priv, bundle);
152+
u16 flags;
153+
154+
flags = pbundle->uattrs[attr->ptr_attr.uattr_idx].flags |
155+
UVERBS_ATTR_F_VALID_OUTPUT;
156+
if (put_user(flags,
157+
&pbundle->user_attrs[attr->ptr_attr.uattr_idx].flags))
158+
return -EFAULT;
159+
return 0;
160+
}
161+
147162
static int uverbs_process_idrs_array(struct bundle_priv *pbundle,
148163
const struct uverbs_api_attr *attr_uapi,
149164
struct uverbs_objs_arr_attr *attr,
@@ -455,6 +470,19 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle,
455470
ret = handler(&pbundle->bundle);
456471
}
457472

473+
/*
474+
* Until the drivers are revised to use the bundle directly we have to
475+
* assume that the driver wrote to its UHW_OUT and flag userspace
476+
* appropriately.
477+
*/
478+
if (!ret && pbundle->method_elm->has_udata) {
479+
const struct uverbs_attr *attr =
480+
uverbs_attr_get(&pbundle->bundle, UVERBS_ATTR_UHW_OUT);
481+
482+
if (!IS_ERR(attr))
483+
ret = uverbs_set_output(&pbundle->bundle, attr);
484+
}
485+
458486
/*
459487
* EPROTONOSUPPORT is ONLY to be returned if the ioctl framework can
460488
* not invoke the method because the request is not supported. No
@@ -706,10 +734,7 @@ void uverbs_fill_udata(struct uverbs_attr_bundle *bundle,
706734
int uverbs_copy_to(const struct uverbs_attr_bundle *bundle, size_t idx,
707735
const void *from, size_t size)
708736
{
709-
struct bundle_priv *pbundle =
710-
container_of(bundle, struct bundle_priv, bundle);
711737
const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx);
712-
u16 flags;
713738
size_t min_size;
714739

715740
if (IS_ERR(attr))
@@ -719,16 +744,25 @@ int uverbs_copy_to(const struct uverbs_attr_bundle *bundle, size_t idx,
719744
if (copy_to_user(u64_to_user_ptr(attr->ptr_attr.data), from, min_size))
720745
return -EFAULT;
721746

722-
flags = pbundle->uattrs[attr->ptr_attr.uattr_idx].flags |
723-
UVERBS_ATTR_F_VALID_OUTPUT;
724-
if (put_user(flags,
725-
&pbundle->user_attrs[attr->ptr_attr.uattr_idx].flags))
726-
return -EFAULT;
727-
728-
return 0;
747+
return uverbs_set_output(bundle, attr);
729748
}
730749
EXPORT_SYMBOL(uverbs_copy_to);
731750

751+
752+
/*
753+
* This is only used if the caller has directly used copy_to_use to write the
754+
* data. It signals to user space that the buffer is filled in.
755+
*/
756+
int uverbs_output_written(const struct uverbs_attr_bundle *bundle, size_t idx)
757+
{
758+
const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx);
759+
760+
if (IS_ERR(attr))
761+
return PTR_ERR(attr);
762+
763+
return uverbs_set_output(bundle, attr);
764+
}
765+
732766
int _uverbs_get_const(s64 *to, const struct uverbs_attr_bundle *attrs_bundle,
733767
size_t idx, s64 lower_bound, u64 upper_bound,
734768
s64 *def_val)
@@ -757,8 +791,10 @@ int uverbs_copy_to_struct_or_zero(const struct uverbs_attr_bundle *bundle,
757791
{
758792
const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx);
759793

760-
if (clear_user(u64_to_user_ptr(attr->ptr_attr.data),
761-
attr->ptr_attr.len))
762-
return -EFAULT;
794+
if (size < attr->ptr_attr.len) {
795+
if (clear_user(u64_to_user_ptr(attr->ptr_attr.data) + size,
796+
attr->ptr_attr.len - size))
797+
return -EFAULT;
798+
}
763799
return uverbs_copy_to(bundle, idx, from, size);
764800
}

drivers/infiniband/core/uverbs_main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,7 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
690690

691691
buf += sizeof(hdr);
692692

693+
memset(bundle.attr_present, 0, sizeof(bundle.attr_present));
693694
bundle.ufile = file;
694695
if (!method_elm->is_ex) {
695696
size_t in_len = hdr.in_words * 4 - sizeof(hdr);

drivers/infiniband/hw/mthca/mthca_provider.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
534534
{
535535
struct mthca_ucontext *context;
536536

537-
qp = kmalloc(sizeof *qp, GFP_KERNEL);
537+
qp = kzalloc(sizeof(*qp), GFP_KERNEL);
538538
if (!qp)
539539
return ERR_PTR(-ENOMEM);
540540

@@ -600,7 +600,7 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
600600
if (udata)
601601
return ERR_PTR(-EINVAL);
602602

603-
qp = kmalloc(sizeof (struct mthca_sqp), GFP_KERNEL);
603+
qp = kzalloc(sizeof(struct mthca_sqp), GFP_KERNEL);
604604
if (!qp)
605605
return ERR_PTR(-ENOMEM);
606606

drivers/infiniband/hw/vmw_pvrdma/pvrdma.h

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,40 @@ static inline enum ib_qp_state pvrdma_qp_state_to_ib(enum pvrdma_qp_state state)
427427

428428
static inline enum pvrdma_wr_opcode ib_wr_opcode_to_pvrdma(enum ib_wr_opcode op)
429429
{
430-
return (enum pvrdma_wr_opcode)op;
430+
switch (op) {
431+
case IB_WR_RDMA_WRITE:
432+
return PVRDMA_WR_RDMA_WRITE;
433+
case IB_WR_RDMA_WRITE_WITH_IMM:
434+
return PVRDMA_WR_RDMA_WRITE_WITH_IMM;
435+
case IB_WR_SEND:
436+
return PVRDMA_WR_SEND;
437+
case IB_WR_SEND_WITH_IMM:
438+
return PVRDMA_WR_SEND_WITH_IMM;
439+
case IB_WR_RDMA_READ:
440+
return PVRDMA_WR_RDMA_READ;
441+
case IB_WR_ATOMIC_CMP_AND_SWP:
442+
return PVRDMA_WR_ATOMIC_CMP_AND_SWP;
443+
case IB_WR_ATOMIC_FETCH_AND_ADD:
444+
return PVRDMA_WR_ATOMIC_FETCH_AND_ADD;
445+
case IB_WR_LSO:
446+
return PVRDMA_WR_LSO;
447+
case IB_WR_SEND_WITH_INV:
448+
return PVRDMA_WR_SEND_WITH_INV;
449+
case IB_WR_RDMA_READ_WITH_INV:
450+
return PVRDMA_WR_RDMA_READ_WITH_INV;
451+
case IB_WR_LOCAL_INV:
452+
return PVRDMA_WR_LOCAL_INV;
453+
case IB_WR_REG_MR:
454+
return PVRDMA_WR_FAST_REG_MR;
455+
case IB_WR_MASKED_ATOMIC_CMP_AND_SWP:
456+
return PVRDMA_WR_MASKED_ATOMIC_CMP_AND_SWP;
457+
case IB_WR_MASKED_ATOMIC_FETCH_AND_ADD:
458+
return PVRDMA_WR_MASKED_ATOMIC_FETCH_AND_ADD;
459+
case IB_WR_REG_SIG_MR:
460+
return PVRDMA_WR_REG_SIG_MR;
461+
default:
462+
return PVRDMA_WR_ERROR;
463+
}
431464
}
432465

433466
static inline enum ib_wc_status pvrdma_wc_status_to_ib(

drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,12 @@ int pvrdma_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr,
721721
wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM)
722722
wqe_hdr->ex.imm_data = wr->ex.imm_data;
723723

724+
if (unlikely(wqe_hdr->opcode == PVRDMA_WR_ERROR)) {
725+
*bad_wr = wr;
726+
ret = -EINVAL;
727+
goto out;
728+
}
729+
724730
switch (qp->ibqp.qp_type) {
725731
case IB_QPT_GSI:
726732
case IB_QPT_UD:

include/uapi/rdma/vmw_pvrdma-abi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ enum pvrdma_wr_opcode {
7878
PVRDMA_WR_MASKED_ATOMIC_FETCH_AND_ADD,
7979
PVRDMA_WR_BIND_MW,
8080
PVRDMA_WR_REG_SIG_MR,
81+
PVRDMA_WR_ERROR,
8182
};
8283

8384
enum pvrdma_wc_status {

0 commit comments

Comments
 (0)