Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

RDMA: Add ib_respond_udata()

Wrap the common copy_to_user() pattern used in drivers and enhance it
to zero pad as well. Include debug logging on failures.

Link: https://patch.msgid.link/r/5-v3-bd56dd443069+49-bnxt_re_uapi_jgg@nvidia.com
Tested-by: Sriharsha Basavapatna <sriharsha.basavapatna@broadcom.com>
Acked-by: Sriharsha Basavapatna <sriharsha.basavapatna@broadcom.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>

+57
+24
drivers/infiniband/core/uverbs_ioctl.c
··· 910 910 return -EOPNOTSUPP; 911 911 } 912 912 EXPORT_SYMBOL(_ib_copy_validate_udata_cm_fail); 913 + 914 + int _ib_respond_udata(struct ib_udata *udata, const void *src, size_t len) 915 + { 916 + size_t copy_len; 917 + 918 + /* 0 length copy_len is a NOP for copy_to_user() and doesn't fail. */ 919 + copy_len = min(len, udata->outlen); 920 + if (copy_to_user(udata->outbuf, src, copy_len)) 921 + goto err_fault; 922 + if (copy_len < udata->outlen) { 923 + if (clear_user(udata->outbuf + copy_len, 924 + udata->outlen - copy_len)) 925 + goto err_fault; 926 + } 927 + return 0; 928 + err_fault: 929 + ibdev_dbg( 930 + rdma_udata_to_dev(udata), 931 + "System call driver out udata has EFAULT (%zu into %zu) for ioctl %ps called by %pSR\n", 932 + len, udata->outlen, uverbs_get_handler_fn(udata), 933 + __builtin_return_address(0)); 934 + return -EFAULT; 935 + } 936 + EXPORT_SYMBOL(_ib_respond_udata);
+33
include/rdma/uverbs_ioctl.h
··· 900 900 901 901 int _ib_copy_validate_udata_in(struct ib_udata *udata, void *req, 902 902 size_t kernel_size, size_t minimum_size); 903 + int _ib_respond_udata(struct ib_udata *udata, const void *src, size_t len); 903 904 #else 904 905 static inline int 905 906 uverbs_get_flags64(u64 *to, const struct uverbs_attr_bundle *attrs_bundle, ··· 965 964 return -EINVAL; 966 965 } 967 966 967 + static inline int _ib_respond_udata(struct ib_udata *udata, const void *src, 968 + size_t len) 969 + { 970 + return -EINVAL; 971 + } 968 972 #endif 969 973 970 974 #define uverbs_get_const_signed(_to, _attrs_bundle, _idx) \ ··· 1074 1068 _udata, (_req).comp_mask, __valid_cm); \ 1075 1069 ret; \ 1076 1070 }) 1071 + 1072 + /** 1073 + * ib_respond_udata - Copy a driver data response to userspace 1074 + * @_udata: The system calls ib_udata struct 1075 + * @_rep: Kernel buffer containing the response driver data on the stack 1076 + * 1077 + * Copy driver data response structures back to userspace in a way that 1078 + * is forwards and backwards compatible. Longer kernel structs are truncated, 1079 + * userspace has made some kind of error if it needed the truncated information. 1080 + * Shorter structs are zero padded. 1081 + */ 1082 + #define ib_respond_udata(_udata, _rep) \ 1083 + _ib_respond_udata(_udata, &(_rep), sizeof(_rep)) 1084 + 1085 + /** 1086 + * ib_respond_empty_udata - Zero fill the response buffer to userspace 1087 + * @_udata: The system calls ib_udata struct 1088 + * 1089 + * Used when there is no driver response data to return. Provides forward 1090 + * compatability by zeroing any buffer the user may have provided. 1091 + */ 1092 + static inline int ib_respond_empty_udata(struct ib_udata *udata) 1093 + { 1094 + if (udata && udata->outlen && clear_user(udata->outbuf, udata->outlen)) 1095 + return -EFAULT; 1096 + return 0; 1097 + } 1077 1098 1078 1099 #endif