aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);