aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Gunthorpe <jgg@mellanox.com>2019-01-11 01:21:44 -0500
committerJason Gunthorpe <jgg@mellanox.com>2019-01-14 16:02:22 -0500
commitd6f4a21f309dfe10a5693ad236358dd6fcc46f7a (patch)
treee900ea13c1f32a17f7d7a9fe059d030c38ee5d3b
parent9d9f59b4204bc41896c866b3e5856e5b416aa199 (diff)
RDMA/uverbs: Mark ioctl responses with UVERBS_ATTR_F_VALID_OUTPUT
When the ioctl interface for the write commands was introduced it did not mark the core response with UVERBS_ATTR_F_VALID_OUTPUT. This causes rdma-core in userspace to not mark the buffers as written for valgrind. Along the same lines it turns out we have always missed marking the driver data. Fixing both of these makes valgrind work properly with rdma-core and ioctl. Fixes: 4785860e04bc ("RDMA/uverbs: Implement an ioctl that can call write and write_ex handlers") Signed-off-by: Jason Gunthorpe <jgg@mellanox.com> Reviewed-by: Artemy Kovalyov <artemyko@mellanox.com> Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
-rw-r--r--drivers/infiniband/core/rdma_core.h2
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c7
-rw-r--r--drivers/infiniband/core/uverbs_ioctl.c62
-rw-r--r--drivers/infiniband/core/uverbs_main.c1
4 files changed, 59 insertions, 13 deletions
diff --git a/drivers/infiniband/core/rdma_core.h b/drivers/infiniband/core/rdma_core.h
index be6b8e1257d0..69f8db66925e 100644
--- a/drivers/infiniband/core/rdma_core.h
+++ b/drivers/infiniband/core/rdma_core.h
@@ -106,6 +106,8 @@ int uverbs_finalize_object(struct ib_uobject *uobj,
106 enum uverbs_obj_access access, 106 enum uverbs_obj_access access,
107 bool commit); 107 bool commit);
108 108
109int uverbs_output_written(const struct uverbs_attr_bundle *bundle, size_t idx);
110
109void setup_ufile_idr_uobject(struct ib_uverbs_file *ufile); 111void setup_ufile_idr_uobject(struct ib_uverbs_file *ufile);
110void release_ufile_idr_uobject(struct ib_uverbs_file *ufile); 112void release_ufile_idr_uobject(struct ib_uverbs_file *ufile);
111 113
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 1b82cb74276c..3317300ab036 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -60,6 +60,10 @@ static int uverbs_response(struct uverbs_attr_bundle *attrs, const void *resp,
60{ 60{
61 int ret; 61 int ret;
62 62
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
63 if (copy_to_user(attrs->ucore.outbuf, resp, 67 if (copy_to_user(attrs->ucore.outbuf, resp,
64 min(attrs->ucore.outlen, resp_len))) 68 min(attrs->ucore.outlen, resp_len)))
65 return -EFAULT; 69 return -EFAULT;
@@ -1181,6 +1185,9 @@ static int ib_uverbs_poll_cq(struct uverbs_attr_bundle *attrs)
1181 goto out_put; 1185 goto out_put;
1182 } 1186 }
1183 1187
1188 if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_CORE_OUT))
1189 ret = uverbs_output_written(attrs, UVERBS_ATTR_CORE_OUT);
1190
1184 ret = 0; 1191 ret = 0;
1185 1192
1186out_put: 1193out_put:
diff --git a/drivers/infiniband/core/uverbs_ioctl.c b/drivers/infiniband/core/uverbs_ioctl.c
index 8c81ff698052..0ca04d224015 100644
--- a/drivers/infiniband/core/uverbs_ioctl.c
+++ b/drivers/infiniband/core/uverbs_ioctl.c
@@ -144,6 +144,21 @@ static bool uverbs_is_attr_cleared(const struct ib_uverbs_attr *uattr,
144 0, uattr->len - len); 144 0, uattr->len - len);
145} 145}
146 146
147static 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
147static int uverbs_process_idrs_array(struct bundle_priv *pbundle, 162static int uverbs_process_idrs_array(struct bundle_priv *pbundle,
148 const struct uverbs_api_attr *attr_uapi, 163 const struct uverbs_api_attr *attr_uapi,
149 struct uverbs_objs_arr_attr *attr, 164 struct uverbs_objs_arr_attr *attr,
@@ -456,6 +471,19 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle,
456 } 471 }
457 472
458 /* 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
486 /*
459 * EPROTONOSUPPORT is ONLY to be returned if the ioctl framework can 487 * EPROTONOSUPPORT is ONLY to be returned if the ioctl framework can
460 * not invoke the method because the request is not supported. No 488 * not invoke the method because the request is not supported. No
461 * other cases should return this code. 489 * other cases should return this code.
@@ -706,10 +734,7 @@ void uverbs_fill_udata(struct uverbs_attr_bundle *bundle,
706int uverbs_copy_to(const struct uverbs_attr_bundle *bundle, size_t idx, 734int uverbs_copy_to(const struct uverbs_attr_bundle *bundle, size_t idx,
707 const void *from, size_t size) 735 const void *from, size_t size)
708{ 736{
709 struct bundle_priv *pbundle =
710 container_of(bundle, struct bundle_priv, bundle);
711 const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx); 737 const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx);
712 u16 flags;
713 size_t min_size; 738 size_t min_size;
714 739
715 if (IS_ERR(attr)) 740 if (IS_ERR(attr))
@@ -719,16 +744,25 @@ int uverbs_copy_to(const struct uverbs_attr_bundle *bundle, size_t idx,
719 if (copy_to_user(u64_to_user_ptr(attr->ptr_attr.data), from, min_size)) 744 if (copy_to_user(u64_to_user_ptr(attr->ptr_attr.data), from, min_size))
720 return -EFAULT; 745 return -EFAULT;
721 746
722 flags = pbundle->uattrs[attr->ptr_attr.uattr_idx].flags | 747 return uverbs_set_output(bundle, attr);
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;
729} 748}
730EXPORT_SYMBOL(uverbs_copy_to); 749EXPORT_SYMBOL(uverbs_copy_to);
731 750
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 */
756int 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
732int _uverbs_get_const(s64 *to, const struct uverbs_attr_bundle *attrs_bundle, 766int _uverbs_get_const(s64 *to, const struct uverbs_attr_bundle *attrs_bundle,
733 size_t idx, s64 lower_bound, u64 upper_bound, 767 size_t idx, s64 lower_bound, u64 upper_bound,
734 s64 *def_val) 768 s64 *def_val)
@@ -757,8 +791,10 @@ int uverbs_copy_to_struct_or_zero(const struct uverbs_attr_bundle *bundle,
757{ 791{
758 const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx); 792 const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx);
759 793
760 if (clear_user(u64_to_user_ptr(attr->ptr_attr.data), 794 if (size < attr->ptr_attr.len) {
761 attr->ptr_attr.len)) 795 if (clear_user(u64_to_user_ptr(attr->ptr_attr.data) + size,
762 return -EFAULT; 796 attr->ptr_attr.len - size))
797 return -EFAULT;
798 }
763 return uverbs_copy_to(bundle, idx, from, size); 799 return uverbs_copy_to(bundle, idx, from, size);
764} 800}
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index fb0007aa0c27..2890a77339e1 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -690,6 +690,7 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
690 690
691 buf += sizeof(hdr); 691 buf += sizeof(hdr);
692 692
693 memset(bundle.attr_present, 0, sizeof(bundle.attr_present));
693 bundle.ufile = file; 694 bundle.ufile = file;
694 if (!method_elm->is_ex) { 695 if (!method_elm->is_ex) {
695 size_t in_len = hdr.in_words * 4 - sizeof(hdr); 696 size_t in_len = hdr.in_words * 4 - sizeof(hdr);