diff options
| -rw-r--r-- | drivers/infiniband/core/rdma_core.h | 2 | ||||
| -rw-r--r-- | drivers/infiniband/core/uverbs_cmd.c | 7 | ||||
| -rw-r--r-- | drivers/infiniband/core/uverbs_ioctl.c | 62 | ||||
| -rw-r--r-- | drivers/infiniband/core/uverbs_main.c | 1 |
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 | ||
| 109 | int uverbs_output_written(const struct uverbs_attr_bundle *bundle, size_t idx); | ||
| 110 | |||
| 109 | void setup_ufile_idr_uobject(struct ib_uverbs_file *ufile); | 111 | void setup_ufile_idr_uobject(struct ib_uverbs_file *ufile); |
| 110 | void release_ufile_idr_uobject(struct ib_uverbs_file *ufile); | 112 | void 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 | ||
| 1186 | out_put: | 1193 | out_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 | ||
| 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 | |||
| 147 | static int uverbs_process_idrs_array(struct bundle_priv *pbundle, | 162 | static 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, | |||
| 706 | int uverbs_copy_to(const struct uverbs_attr_bundle *bundle, size_t idx, | 734 | int 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 | } |
| 730 | EXPORT_SYMBOL(uverbs_copy_to); | 749 | EXPORT_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 | */ | ||
| 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 | |||
| 732 | int _uverbs_get_const(s64 *to, const struct uverbs_attr_bundle *attrs_bundle, | 766 | int _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); |
