uverbs_ioctl.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
  1. /*
  2. * Copyright (c) 2017, Mellanox Technologies inc. All rights reserved.
  3. *
  4. * This software is available to you under a choice of one of two
  5. * licenses. You may choose to be licensed under the terms of the GNU
  6. * General Public License (GPL) Version 2, available from the file
  7. * COPYING in the main directory of this source tree, or the
  8. * OpenIB.org BSD license below:
  9. *
  10. * Redistribution and use in source and binary forms, with or
  11. * without modification, are permitted provided that the following
  12. * conditions are met:
  13. *
  14. * - Redistributions of source code must retain the above
  15. * copyright notice, this list of conditions and the following
  16. * disclaimer.
  17. *
  18. * - Redistributions in binary form must reproduce the above
  19. * copyright notice, this list of conditions and the following
  20. * disclaimer in the documentation and/or other materials
  21. * provided with the distribution.
  22. *
  23. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  27. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  28. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  29. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  30. * SOFTWARE.
  31. */
  32. #include <rdma/rdma_user_ioctl.h>
  33. #include <rdma/uverbs_ioctl.h>
  34. #include "rdma_core.h"
  35. #include "uverbs.h"
  36. struct bundle_alloc_head {
  37. struct bundle_alloc_head *next;
  38. u8 data[];
  39. };
  40. struct bundle_priv {
  41. /* Must be first */
  42. struct bundle_alloc_head alloc_head;
  43. struct bundle_alloc_head *allocated_mem;
  44. size_t internal_avail;
  45. size_t internal_used;
  46. struct radix_tree_root *radix;
  47. const struct uverbs_api_ioctl_method *method_elm;
  48. void __rcu **radix_slots;
  49. unsigned long radix_slots_len;
  50. u32 method_key;
  51. struct ib_uverbs_attr __user *user_attrs;
  52. struct ib_uverbs_attr *uattrs;
  53. DECLARE_BITMAP(uobj_finalize, UVERBS_API_ATTR_BKEY_LEN);
  54. /*
  55. * Must be last. bundle ends in a flex array which overlaps
  56. * internal_buffer.
  57. */
  58. struct uverbs_attr_bundle bundle;
  59. u64 internal_buffer[32];
  60. };
  61. /*
  62. * Each method has an absolute minimum amount of memory it needs to allocate,
  63. * precompute that amount and determine if the onstack memory can be used or
  64. * if allocation is need.
  65. */
  66. void uapi_compute_bundle_size(struct uverbs_api_ioctl_method *method_elm,
  67. unsigned int num_attrs)
  68. {
  69. struct bundle_priv *pbundle;
  70. size_t bundle_size =
  71. offsetof(struct bundle_priv, internal_buffer) +
  72. sizeof(*pbundle->bundle.attrs) * method_elm->key_bitmap_len +
  73. sizeof(*pbundle->uattrs) * num_attrs;
  74. method_elm->use_stack = bundle_size <= sizeof(*pbundle);
  75. method_elm->bundle_size =
  76. ALIGN(bundle_size + 256, sizeof(*pbundle->internal_buffer));
  77. /* Do not want order-2 allocations for this. */
  78. WARN_ON_ONCE(method_elm->bundle_size > PAGE_SIZE);
  79. }
  80. /**
  81. * uverbs_alloc() - Quickly allocate memory for use with a bundle
  82. * @bundle: The bundle
  83. * @size: Number of bytes to allocate
  84. * @flags: Allocator flags
  85. *
  86. * The bundle allocator is intended for allocations that are connected with
  87. * processing the system call related to the bundle. The allocated memory is
  88. * always freed once the system call completes, and cannot be freed any other
  89. * way.
  90. *
  91. * This tries to use a small pool of pre-allocated memory for performance.
  92. */
  93. __malloc void *_uverbs_alloc(struct uverbs_attr_bundle *bundle, size_t size,
  94. gfp_t flags)
  95. {
  96. struct bundle_priv *pbundle =
  97. container_of(bundle, struct bundle_priv, bundle);
  98. size_t new_used;
  99. void *res;
  100. if (check_add_overflow(size, pbundle->internal_used, &new_used))
  101. return ERR_PTR(-EOVERFLOW);
  102. if (new_used > pbundle->internal_avail) {
  103. struct bundle_alloc_head *buf;
  104. buf = kvmalloc(struct_size(buf, data, size), flags);
  105. if (!buf)
  106. return ERR_PTR(-ENOMEM);
  107. buf->next = pbundle->allocated_mem;
  108. pbundle->allocated_mem = buf;
  109. return buf->data;
  110. }
  111. res = (void *)pbundle->internal_buffer + pbundle->internal_used;
  112. pbundle->internal_used =
  113. ALIGN(new_used, sizeof(*pbundle->internal_buffer));
  114. if (flags & __GFP_ZERO)
  115. memset(res, 0, size);
  116. return res;
  117. }
  118. EXPORT_SYMBOL(_uverbs_alloc);
  119. static bool uverbs_is_attr_cleared(const struct ib_uverbs_attr *uattr,
  120. u16 len)
  121. {
  122. if (uattr->len > sizeof(((struct ib_uverbs_attr *)0)->data))
  123. return ib_is_buffer_cleared(u64_to_user_ptr(uattr->data) + len,
  124. uattr->len - len);
  125. return !memchr_inv((const void *)&uattr->data + len,
  126. 0, uattr->len - len);
  127. }
  128. static int uverbs_process_attr(struct bundle_priv *pbundle,
  129. const struct uverbs_api_attr *attr_uapi,
  130. struct ib_uverbs_attr *uattr, u32 attr_bkey)
  131. {
  132. const struct uverbs_attr_spec *spec = &attr_uapi->spec;
  133. struct uverbs_attr *e = &pbundle->bundle.attrs[attr_bkey];
  134. const struct uverbs_attr_spec *val_spec = spec;
  135. struct uverbs_obj_attr *o_attr;
  136. switch (spec->type) {
  137. case UVERBS_ATTR_TYPE_ENUM_IN:
  138. if (uattr->attr_data.enum_data.elem_id >= spec->u.enum_def.num_elems)
  139. return -EOPNOTSUPP;
  140. if (uattr->attr_data.enum_data.reserved)
  141. return -EINVAL;
  142. val_spec = &spec->u2.enum_def.ids[uattr->attr_data.enum_data.elem_id];
  143. /* Currently we only support PTR_IN based enums */
  144. if (val_spec->type != UVERBS_ATTR_TYPE_PTR_IN)
  145. return -EOPNOTSUPP;
  146. e->ptr_attr.enum_id = uattr->attr_data.enum_data.elem_id;
  147. /* fall through */
  148. case UVERBS_ATTR_TYPE_PTR_IN:
  149. /* Ensure that any data provided by userspace beyond the known
  150. * struct is zero. Userspace that knows how to use some future
  151. * longer struct will fail here if used with an old kernel and
  152. * non-zero content, making ABI compat/discovery simpler.
  153. */
  154. if (uattr->len > val_spec->u.ptr.len &&
  155. val_spec->zero_trailing &&
  156. !uverbs_is_attr_cleared(uattr, val_spec->u.ptr.len))
  157. return -EOPNOTSUPP;
  158. /* fall through */
  159. case UVERBS_ATTR_TYPE_PTR_OUT:
  160. if (uattr->len < val_spec->u.ptr.min_len ||
  161. (!val_spec->zero_trailing &&
  162. uattr->len > val_spec->u.ptr.len))
  163. return -EINVAL;
  164. if (spec->type != UVERBS_ATTR_TYPE_ENUM_IN &&
  165. uattr->attr_data.reserved)
  166. return -EINVAL;
  167. e->ptr_attr.uattr_idx = uattr - pbundle->uattrs;
  168. e->ptr_attr.len = uattr->len;
  169. if (val_spec->alloc_and_copy && !uverbs_attr_ptr_is_inline(e)) {
  170. void *p;
  171. p = uverbs_alloc(&pbundle->bundle, uattr->len);
  172. if (IS_ERR(p))
  173. return PTR_ERR(p);
  174. e->ptr_attr.ptr = p;
  175. if (copy_from_user(p, u64_to_user_ptr(uattr->data),
  176. uattr->len))
  177. return -EFAULT;
  178. } else {
  179. e->ptr_attr.data = uattr->data;
  180. }
  181. break;
  182. case UVERBS_ATTR_TYPE_IDR:
  183. case UVERBS_ATTR_TYPE_FD:
  184. if (uattr->attr_data.reserved)
  185. return -EINVAL;
  186. if (uattr->len != 0)
  187. return -EINVAL;
  188. o_attr = &e->obj_attr;
  189. o_attr->attr_elm = attr_uapi;
  190. /*
  191. * The type of uattr->data is u64 for UVERBS_ATTR_TYPE_IDR and
  192. * s64 for UVERBS_ATTR_TYPE_FD. We can cast the u64 to s64
  193. * here without caring about truncation as we know that the
  194. * IDR implementation today rejects negative IDs
  195. */
  196. o_attr->uobject = uverbs_get_uobject_from_file(
  197. spec->u.obj.obj_type,
  198. pbundle->bundle.ufile,
  199. spec->u.obj.access,
  200. uattr->data_s64);
  201. if (IS_ERR(o_attr->uobject))
  202. return PTR_ERR(o_attr->uobject);
  203. __set_bit(attr_bkey, pbundle->uobj_finalize);
  204. if (spec->u.obj.access == UVERBS_ACCESS_NEW) {
  205. unsigned int uattr_idx = uattr - pbundle->uattrs;
  206. s64 id = o_attr->uobject->id;
  207. /* Copy the allocated id to the user-space */
  208. if (put_user(id, &pbundle->user_attrs[uattr_idx].data))
  209. return -EFAULT;
  210. }
  211. break;
  212. default:
  213. return -EOPNOTSUPP;
  214. }
  215. return 0;
  216. }
  217. /*
  218. * We search the radix tree with the method prefix and now we want to fast
  219. * search the suffix bits to get a particular attribute pointer. It is not
  220. * totally clear to me if this breaks the radix tree encasulation or not, but
  221. * it uses the iter data to determine if the method iter points at the same
  222. * chunk that will store the attribute, if so it just derefs it directly. By
  223. * construction in most kernel configs the method and attrs will all fit in a
  224. * single radix chunk, so in most cases this will have no search. Other cases
  225. * this falls back to a full search.
  226. */
  227. static void __rcu **uapi_get_attr_for_method(struct bundle_priv *pbundle,
  228. u32 attr_key)
  229. {
  230. void __rcu **slot;
  231. if (likely(attr_key < pbundle->radix_slots_len)) {
  232. void *entry;
  233. slot = pbundle->radix_slots + attr_key;
  234. entry = rcu_dereference_raw(*slot);
  235. if (likely(!radix_tree_is_internal_node(entry) && entry))
  236. return slot;
  237. }
  238. return radix_tree_lookup_slot(pbundle->radix,
  239. pbundle->method_key | attr_key);
  240. }
  241. static int uverbs_set_attr(struct bundle_priv *pbundle,
  242. struct ib_uverbs_attr *uattr)
  243. {
  244. u32 attr_key = uapi_key_attr(uattr->attr_id);
  245. u32 attr_bkey = uapi_bkey_attr(attr_key);
  246. const struct uverbs_api_attr *attr;
  247. void __rcu **slot;
  248. int ret;
  249. slot = uapi_get_attr_for_method(pbundle, attr_key);
  250. if (!slot) {
  251. /*
  252. * Kernel does not support the attribute but user-space says it
  253. * is mandatory
  254. */
  255. if (uattr->flags & UVERBS_ATTR_F_MANDATORY)
  256. return -EPROTONOSUPPORT;
  257. return 0;
  258. }
  259. attr = srcu_dereference(
  260. *slot, &pbundle->bundle.ufile->device->disassociate_srcu);
  261. /* Reject duplicate attributes from user-space */
  262. if (test_bit(attr_bkey, pbundle->bundle.attr_present))
  263. return -EINVAL;
  264. ret = uverbs_process_attr(pbundle, attr, uattr, attr_bkey);
  265. if (ret)
  266. return ret;
  267. __set_bit(attr_bkey, pbundle->bundle.attr_present);
  268. return 0;
  269. }
  270. static int ib_uverbs_run_method(struct bundle_priv *pbundle,
  271. unsigned int num_attrs)
  272. {
  273. int (*handler)(struct ib_uverbs_file *ufile,
  274. struct uverbs_attr_bundle *ctx);
  275. size_t uattrs_size = array_size(sizeof(*pbundle->uattrs), num_attrs);
  276. unsigned int destroy_bkey = pbundle->method_elm->destroy_bkey;
  277. unsigned int i;
  278. int ret;
  279. /* See uverbs_disassociate_api() */
  280. handler = srcu_dereference(
  281. pbundle->method_elm->handler,
  282. &pbundle->bundle.ufile->device->disassociate_srcu);
  283. if (!handler)
  284. return -EIO;
  285. pbundle->uattrs = uverbs_alloc(&pbundle->bundle, uattrs_size);
  286. if (IS_ERR(pbundle->uattrs))
  287. return PTR_ERR(pbundle->uattrs);
  288. if (copy_from_user(pbundle->uattrs, pbundle->user_attrs, uattrs_size))
  289. return -EFAULT;
  290. for (i = 0; i != num_attrs; i++) {
  291. ret = uverbs_set_attr(pbundle, &pbundle->uattrs[i]);
  292. if (unlikely(ret))
  293. return ret;
  294. }
  295. /* User space did not provide all the mandatory attributes */
  296. if (unlikely(!bitmap_subset(pbundle->method_elm->attr_mandatory,
  297. pbundle->bundle.attr_present,
  298. pbundle->method_elm->key_bitmap_len)))
  299. return -EINVAL;
  300. if (destroy_bkey != UVERBS_API_ATTR_BKEY_LEN) {
  301. struct uverbs_obj_attr *destroy_attr =
  302. &pbundle->bundle.attrs[destroy_bkey].obj_attr;
  303. ret = uobj_destroy(destroy_attr->uobject);
  304. if (ret)
  305. return ret;
  306. __clear_bit(destroy_bkey, pbundle->uobj_finalize);
  307. ret = handler(pbundle->bundle.ufile, &pbundle->bundle);
  308. uobj_put_destroy(destroy_attr->uobject);
  309. } else {
  310. ret = handler(pbundle->bundle.ufile, &pbundle->bundle);
  311. }
  312. /*
  313. * EPROTONOSUPPORT is ONLY to be returned if the ioctl framework can
  314. * not invoke the method because the request is not supported. No
  315. * other cases should return this code.
  316. */
  317. if (WARN_ON_ONCE(ret == -EPROTONOSUPPORT))
  318. return -EINVAL;
  319. return ret;
  320. }
  321. static int bundle_destroy(struct bundle_priv *pbundle, bool commit)
  322. {
  323. unsigned int key_bitmap_len = pbundle->method_elm->key_bitmap_len;
  324. struct bundle_alloc_head *memblock;
  325. unsigned int i;
  326. int ret = 0;
  327. i = -1;
  328. while ((i = find_next_bit(pbundle->uobj_finalize, key_bitmap_len,
  329. i + 1)) < key_bitmap_len) {
  330. struct uverbs_attr *attr = &pbundle->bundle.attrs[i];
  331. int current_ret;
  332. current_ret = uverbs_finalize_object(
  333. attr->obj_attr.uobject,
  334. attr->obj_attr.attr_elm->spec.u.obj.access, commit);
  335. if (!ret)
  336. ret = current_ret;
  337. }
  338. for (memblock = pbundle->allocated_mem; memblock;) {
  339. struct bundle_alloc_head *tmp = memblock;
  340. memblock = memblock->next;
  341. kvfree(tmp);
  342. }
  343. return ret;
  344. }
  345. static int ib_uverbs_cmd_verbs(struct ib_uverbs_file *ufile,
  346. struct ib_uverbs_ioctl_hdr *hdr,
  347. struct ib_uverbs_attr __user *user_attrs)
  348. {
  349. const struct uverbs_api_ioctl_method *method_elm;
  350. struct uverbs_api *uapi = ufile->device->uapi;
  351. struct radix_tree_iter attrs_iter;
  352. struct bundle_priv *pbundle;
  353. struct bundle_priv onstack;
  354. void __rcu **slot;
  355. int destroy_ret;
  356. int ret;
  357. if (unlikely(hdr->driver_id != uapi->driver_id))
  358. return -EINVAL;
  359. slot = radix_tree_iter_lookup(
  360. &uapi->radix, &attrs_iter,
  361. uapi_key_obj(hdr->object_id) |
  362. uapi_key_ioctl_method(hdr->method_id));
  363. if (unlikely(!slot))
  364. return -EPROTONOSUPPORT;
  365. method_elm = srcu_dereference(*slot, &ufile->device->disassociate_srcu);
  366. if (!method_elm->use_stack) {
  367. pbundle = kmalloc(method_elm->bundle_size, GFP_KERNEL);
  368. if (!pbundle)
  369. return -ENOMEM;
  370. pbundle->internal_avail =
  371. method_elm->bundle_size -
  372. offsetof(struct bundle_priv, internal_buffer);
  373. pbundle->alloc_head.next = NULL;
  374. pbundle->allocated_mem = &pbundle->alloc_head;
  375. } else {
  376. pbundle = &onstack;
  377. pbundle->internal_avail = sizeof(pbundle->internal_buffer);
  378. pbundle->allocated_mem = NULL;
  379. }
  380. /* Space for the pbundle->bundle.attrs flex array */
  381. pbundle->method_elm = method_elm;
  382. pbundle->method_key = attrs_iter.index;
  383. pbundle->bundle.ufile = ufile;
  384. pbundle->radix = &uapi->radix;
  385. pbundle->radix_slots = slot;
  386. pbundle->radix_slots_len = radix_tree_chunk_size(&attrs_iter);
  387. pbundle->user_attrs = user_attrs;
  388. pbundle->internal_used = ALIGN(pbundle->method_elm->key_bitmap_len *
  389. sizeof(*pbundle->bundle.attrs),
  390. sizeof(*pbundle->internal_buffer));
  391. memset(pbundle->bundle.attr_present, 0,
  392. sizeof(pbundle->bundle.attr_present));
  393. memset(pbundle->uobj_finalize, 0, sizeof(pbundle->uobj_finalize));
  394. ret = ib_uverbs_run_method(pbundle, hdr->num_attrs);
  395. destroy_ret = bundle_destroy(pbundle, ret == 0);
  396. if (unlikely(destroy_ret && !ret))
  397. return destroy_ret;
  398. return ret;
  399. }
  400. long ib_uverbs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  401. {
  402. struct ib_uverbs_file *file = filp->private_data;
  403. struct ib_uverbs_ioctl_hdr __user *user_hdr =
  404. (struct ib_uverbs_ioctl_hdr __user *)arg;
  405. struct ib_uverbs_ioctl_hdr hdr;
  406. int srcu_key;
  407. int err;
  408. if (unlikely(cmd != RDMA_VERBS_IOCTL))
  409. return -ENOIOCTLCMD;
  410. err = copy_from_user(&hdr, user_hdr, sizeof(hdr));
  411. if (err)
  412. return -EFAULT;
  413. if (hdr.length > PAGE_SIZE ||
  414. hdr.length != struct_size(&hdr, attrs, hdr.num_attrs))
  415. return -EINVAL;
  416. if (hdr.reserved1 || hdr.reserved2)
  417. return -EPROTONOSUPPORT;
  418. srcu_key = srcu_read_lock(&file->device->disassociate_srcu);
  419. err = ib_uverbs_cmd_verbs(file, &hdr, user_hdr->attrs);
  420. srcu_read_unlock(&file->device->disassociate_srcu, srcu_key);
  421. return err;
  422. }
  423. int uverbs_get_flags64(u64 *to, const struct uverbs_attr_bundle *attrs_bundle,
  424. size_t idx, u64 allowed_bits)
  425. {
  426. const struct uverbs_attr *attr;
  427. u64 flags;
  428. attr = uverbs_attr_get(attrs_bundle, idx);
  429. /* Missing attribute means 0 flags */
  430. if (IS_ERR(attr)) {
  431. *to = 0;
  432. return 0;
  433. }
  434. /*
  435. * New userspace code should use 8 bytes to pass flags, but we
  436. * transparently support old userspaces that were using 4 bytes as
  437. * well.
  438. */
  439. if (attr->ptr_attr.len == 8)
  440. flags = attr->ptr_attr.data;
  441. else if (attr->ptr_attr.len == 4)
  442. flags = *(u32 *)&attr->ptr_attr.data;
  443. else
  444. return -EINVAL;
  445. if (flags & ~allowed_bits)
  446. return -EINVAL;
  447. *to = flags;
  448. return 0;
  449. }
  450. EXPORT_SYMBOL(uverbs_get_flags64);
  451. int uverbs_get_flags32(u32 *to, const struct uverbs_attr_bundle *attrs_bundle,
  452. size_t idx, u64 allowed_bits)
  453. {
  454. u64 flags;
  455. int ret;
  456. ret = uverbs_get_flags64(&flags, attrs_bundle, idx, allowed_bits);
  457. if (ret)
  458. return ret;
  459. if (flags > U32_MAX)
  460. return -EINVAL;
  461. *to = flags;
  462. return 0;
  463. }
  464. EXPORT_SYMBOL(uverbs_get_flags32);
  465. /*
  466. * This is for ease of conversion. The purpose is to convert all drivers to
  467. * use uverbs_attr_bundle instead of ib_udata. Assume attr == 0 is input and
  468. * attr == 1 is output.
  469. */
  470. void create_udata(struct uverbs_attr_bundle *bundle, struct ib_udata *udata)
  471. {
  472. struct bundle_priv *pbundle =
  473. container_of(bundle, struct bundle_priv, bundle);
  474. const struct uverbs_attr *uhw_in =
  475. uverbs_attr_get(bundle, UVERBS_ATTR_UHW_IN);
  476. const struct uverbs_attr *uhw_out =
  477. uverbs_attr_get(bundle, UVERBS_ATTR_UHW_OUT);
  478. if (!IS_ERR(uhw_in)) {
  479. udata->inlen = uhw_in->ptr_attr.len;
  480. if (uverbs_attr_ptr_is_inline(uhw_in))
  481. udata->inbuf =
  482. &pbundle->user_attrs[uhw_in->ptr_attr.uattr_idx]
  483. .data;
  484. else
  485. udata->inbuf = u64_to_user_ptr(uhw_in->ptr_attr.data);
  486. } else {
  487. udata->inbuf = NULL;
  488. udata->inlen = 0;
  489. }
  490. if (!IS_ERR(uhw_out)) {
  491. udata->outbuf = u64_to_user_ptr(uhw_out->ptr_attr.data);
  492. udata->outlen = uhw_out->ptr_attr.len;
  493. } else {
  494. udata->outbuf = NULL;
  495. udata->outlen = 0;
  496. }
  497. }
  498. int uverbs_copy_to(const struct uverbs_attr_bundle *bundle, size_t idx,
  499. const void *from, size_t size)
  500. {
  501. struct bundle_priv *pbundle =
  502. container_of(bundle, struct bundle_priv, bundle);
  503. const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx);
  504. u16 flags;
  505. size_t min_size;
  506. if (IS_ERR(attr))
  507. return PTR_ERR(attr);
  508. min_size = min_t(size_t, attr->ptr_attr.len, size);
  509. if (copy_to_user(u64_to_user_ptr(attr->ptr_attr.data), from, min_size))
  510. return -EFAULT;
  511. flags = pbundle->uattrs[attr->ptr_attr.uattr_idx].flags |
  512. UVERBS_ATTR_F_VALID_OUTPUT;
  513. if (put_user(flags,
  514. &pbundle->user_attrs[attr->ptr_attr.uattr_idx].flags))
  515. return -EFAULT;
  516. return 0;
  517. }
  518. EXPORT_SYMBOL(uverbs_copy_to);