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 33 #include <linux/radix-tree.h> 34 #include <linux/file.h> 35 #include <linux/overflow.h> 36 37 #include <rdma/rdma_user_ioctl.h> 38 #include <rdma/uverbs_ioctl.h> 39 #include "rdma_core.h" 40 #include "uverbs.h" 41 42 struct bundle_alloc_head { 43 struct bundle_alloc_head *next; 44 uint8_t data[0]; 45 }; 46 47 struct bundle_priv { 48 /* Must be first */ 49 struct bundle_alloc_head alloc_head; 50 struct bundle_alloc_head *allocated_mem; 51 size_t internal_avail; 52 size_t internal_used; 53 54 struct radix_tree_root *radix; 55 const struct uverbs_api_ioctl_method *method_elm; 56 u32 method_key; 57 58 struct ib_uverbs_attr __user *user_attrs; 59 struct ib_uverbs_attr *uattrs; 60 61 DECLARE_BITMAP(uobj_finalize, UVERBS_API_ATTR_BKEY_LEN); 62 DECLARE_BITMAP(spec_finalize, UVERBS_API_ATTR_BKEY_LEN); 63 64 /* 65 * Must be last. bundle ends in a flex array which overlaps 66 * internal_buffer. 67 */ 68 struct uverbs_attr_bundle bundle; 69 u64 internal_buffer[32]; 70 }; 71 72 /* 73 * Each method has an absolute minimum amount of memory it needs to allocate, 74 * precompute that amount and determine if the onstack memory can be used or 75 * if allocation is need. 76 */ 77 void uapi_compute_bundle_size(struct uverbs_api_ioctl_method *method_elm, 78 unsigned int num_attrs) 79 { 80 struct bundle_priv *pbundle; 81 size_t bundle_size = 82 offsetof(struct bundle_priv, internal_buffer) + 83 sizeof(*pbundle->bundle.attrs) * method_elm->key_bitmap_len + 84 sizeof(*pbundle->uattrs) * num_attrs; 85 86 method_elm->use_stack = bundle_size <= sizeof(*pbundle); 87 method_elm->bundle_size = 88 ALIGN(bundle_size + 256, sizeof(*pbundle->internal_buffer)); 89 90 /* Do not want order-2 allocations for this. */ 91 WARN_ON_ONCE(method_elm->bundle_size > PAGE_SIZE); 92 } 93 94 /** 95 * uverbs_alloc() - Quickly allocate memory for use with a bundle 96 * @bundle: The bundle 97 * @size: Number of bytes to allocate 98 * @flags: Allocator flags 99 * 100 * The bundle allocator is intended for allocations that are connected with 101 * processing the system call related to the bundle. The allocated memory is 102 * always freed once the system call completes, and cannot be freed any other 103 * way. 104 * 105 * This tries to use a small pool of pre-allocated memory for performance. 106 */ 107 __malloc void *_uverbs_alloc(struct uverbs_attr_bundle *bundle, size_t size, 108 gfp_t flags) 109 { 110 struct bundle_priv *pbundle = 111 container_of(bundle, struct bundle_priv, bundle); 112 size_t new_used; 113 void *res; 114 115 new_used = size + pbundle->internal_used; 116 if (new_used < size) 117 return ERR_PTR(-EOVERFLOW); 118 119 if (new_used > pbundle->internal_avail) { 120 struct bundle_alloc_head *buf; 121 122 buf = kvmalloc(struct_size(buf, data, size), flags); 123 if (!buf) 124 return ERR_PTR(-ENOMEM); 125 buf->next = pbundle->allocated_mem; 126 pbundle->allocated_mem = buf; 127 return buf->data; 128 } 129 130 res = (u8 *)pbundle->internal_buffer + pbundle->internal_used; 131 pbundle->internal_used = 132 ALIGN(new_used, sizeof(*pbundle->internal_buffer)); 133 if (flags & __GFP_ZERO) 134 memset(res, 0, size); 135 return res; 136 } 137 EXPORT_SYMBOL(_uverbs_alloc); 138 139 static bool uverbs_is_attr_cleared(const struct ib_uverbs_attr *uattr, 140 u16 len) 141 { 142 if (uattr->len > sizeof(((struct ib_uverbs_attr *)0)->data)) 143 return ib_is_buffer_cleared(u64_to_user_ptr(uattr->data + len), 144 uattr->len - len); 145 146 return !memchr_inv((const u8 *)&uattr->data + len, 147 0, uattr->len - len); 148 } 149 150 static int uverbs_set_output(const struct uverbs_attr_bundle *bundle, 151 const struct uverbs_attr *attr) 152 { 153 struct bundle_priv *pbundle = 154 container_of(bundle, struct bundle_priv, bundle); 155 u16 flags; 156 157 flags = pbundle->uattrs[attr->ptr_attr.uattr_idx].flags | 158 UVERBS_ATTR_F_VALID_OUTPUT; 159 if (put_user(flags, 160 &pbundle->user_attrs[attr->ptr_attr.uattr_idx].flags)) 161 return -EFAULT; 162 return 0; 163 } 164 165 static int uverbs_process_idrs_array(struct bundle_priv *pbundle, 166 const struct uverbs_api_attr *attr_uapi, 167 struct uverbs_objs_arr_attr *attr, 168 struct ib_uverbs_attr *uattr, 169 u32 attr_bkey) 170 { 171 const struct uverbs_attr_spec *spec = &attr_uapi->spec; 172 size_t array_len; 173 u32 *idr_vals; 174 int ret = 0; 175 size_t i; 176 177 if (uattr->attr_data.reserved) 178 return -EINVAL; 179 180 if (uattr->len % sizeof(u32)) 181 return -EINVAL; 182 183 array_len = uattr->len / sizeof(u32); 184 if (array_len < spec->u2.objs_arr.min_len || 185 array_len > spec->u2.objs_arr.max_len) 186 return -EINVAL; 187 188 attr->uobjects = 189 uverbs_alloc(&pbundle->bundle, 190 array_size(array_len, sizeof(*attr->uobjects))); 191 if (IS_ERR(attr->uobjects)) 192 return PTR_ERR(attr->uobjects); 193 194 /* 195 * Since idr is 4B and *uobjects is >= 4B, we can use attr->uobjects 196 * to store idrs array and avoid additional memory allocation. The 197 * idrs array is offset to the end of the uobjects array so we will be 198 * able to read idr and replace with a pointer. 199 */ 200 idr_vals = (u32 *)(attr->uobjects + array_len) - array_len; 201 202 if (uattr->len > sizeof(uattr->data)) { 203 ret = copy_from_user(idr_vals, u64_to_user_ptr(uattr->data), 204 uattr->len); 205 if (ret) 206 return -EFAULT; 207 } else { 208 memcpy(idr_vals, &uattr->data, uattr->len); 209 } 210 211 for (i = 0; i != array_len; i++) { 212 attr->uobjects[i] = uverbs_get_uobject_from_file( 213 spec->u2.objs_arr.obj_type, spec->u2.objs_arr.access, 214 idr_vals[i], &pbundle->bundle); 215 if (IS_ERR(attr->uobjects[i])) { 216 ret = PTR_ERR(attr->uobjects[i]); 217 break; 218 } 219 } 220 221 attr->len = i; 222 __set_bit(attr_bkey, pbundle->spec_finalize); 223 return ret; 224 } 225 226 static void uverbs_free_idrs_array(const struct uverbs_api_attr *attr_uapi, 227 struct uverbs_objs_arr_attr *attr, 228 bool commit, 229 struct uverbs_attr_bundle *attrs) 230 { 231 const struct uverbs_attr_spec *spec = &attr_uapi->spec; 232 size_t i; 233 234 for (i = 0; i != attr->len; i++) 235 uverbs_finalize_object(attr->uobjects[i], 236 spec->u2.objs_arr.access, commit, attrs); 237 } 238 239 static int uverbs_process_attr(struct bundle_priv *pbundle, 240 const struct uverbs_api_attr *attr_uapi, 241 struct ib_uverbs_attr *uattr, u32 attr_bkey) 242 { 243 const struct uverbs_attr_spec *spec = &attr_uapi->spec; 244 struct uverbs_attr *e = &pbundle->bundle.attrs[attr_bkey]; 245 const struct uverbs_attr_spec *val_spec = spec; 246 struct uverbs_obj_attr *o_attr; 247 248 switch (spec->type) { 249 case UVERBS_ATTR_TYPE_ENUM_IN: 250 if (uattr->attr_data.enum_data.elem_id >= spec->u.enum_def.num_elems) 251 return -EOPNOTSUPP; 252 253 if (uattr->attr_data.enum_data.reserved) 254 return -EINVAL; 255 256 val_spec = &spec->u2.enum_def.ids[uattr->attr_data.enum_data.elem_id]; 257 258 /* Currently we only support PTR_IN based enums */ 259 if (val_spec->type != UVERBS_ATTR_TYPE_PTR_IN) 260 return -EOPNOTSUPP; 261 262 e->ptr_attr.enum_id = uattr->attr_data.enum_data.elem_id; 263 /* fall through */ 264 case UVERBS_ATTR_TYPE_PTR_IN: 265 /* Ensure that any data provided by userspace beyond the known 266 * struct is zero. Userspace that knows how to use some future 267 * longer struct will fail here if used with an old kernel and 268 * non-zero content, making ABI compat/discovery simpler. 269 */ 270 if (uattr->len > val_spec->u.ptr.len && 271 val_spec->zero_trailing && 272 !uverbs_is_attr_cleared(uattr, val_spec->u.ptr.len)) 273 return -EOPNOTSUPP; 274 275 /* fall through */ 276 case UVERBS_ATTR_TYPE_PTR_OUT: 277 if (uattr->len < val_spec->u.ptr.min_len || 278 (!val_spec->zero_trailing && 279 uattr->len > val_spec->u.ptr.len)) 280 return -EINVAL; 281 282 if (spec->type != UVERBS_ATTR_TYPE_ENUM_IN && 283 uattr->attr_data.reserved) 284 return -EINVAL; 285 286 e->ptr_attr.uattr_idx = uattr - pbundle->uattrs; 287 e->ptr_attr.len = uattr->len; 288 289 if (val_spec->alloc_and_copy && !uverbs_attr_ptr_is_inline(e)) { 290 void *p; 291 292 p = uverbs_alloc(&pbundle->bundle, uattr->len); 293 if (IS_ERR(p)) 294 return PTR_ERR(p); 295 296 e->ptr_attr.ptr = p; 297 298 if (copy_from_user(p, u64_to_user_ptr(uattr->data), 299 uattr->len)) 300 return -EFAULT; 301 } else { 302 e->ptr_attr.data = uattr->data; 303 } 304 break; 305 306 case UVERBS_ATTR_TYPE_IDR: 307 case UVERBS_ATTR_TYPE_FD: 308 if (uattr->attr_data.reserved) 309 return -EINVAL; 310 311 if (uattr->len != 0) 312 return -EINVAL; 313 314 o_attr = &e->obj_attr; 315 o_attr->attr_elm = attr_uapi; 316 317 /* 318 * The type of uattr->data is u64 for UVERBS_ATTR_TYPE_IDR and 319 * s64 for UVERBS_ATTR_TYPE_FD. We can cast the u64 to s64 320 * here without caring about truncation as we know that the 321 * IDR implementation today rejects negative IDs 322 */ 323 o_attr->uobject = uverbs_get_uobject_from_file( 324 spec->u.obj.obj_type, spec->u.obj.access, 325 uattr->data_s64, &pbundle->bundle); 326 if (IS_ERR(o_attr->uobject)) 327 return PTR_ERR(o_attr->uobject); 328 __set_bit(attr_bkey, pbundle->uobj_finalize); 329 330 if (spec->u.obj.access == UVERBS_ACCESS_NEW) { 331 unsigned int uattr_idx = uattr - pbundle->uattrs; 332 s64 id = o_attr->uobject->id; 333 334 /* Copy the allocated id to the user-space */ 335 if (put_user(id, &pbundle->user_attrs[uattr_idx].data)) 336 return -EFAULT; 337 } 338 339 break; 340 341 case UVERBS_ATTR_TYPE_IDRS_ARRAY: 342 return uverbs_process_idrs_array(pbundle, attr_uapi, 343 &e->objs_arr_attr, uattr, 344 attr_bkey); 345 default: 346 return -EOPNOTSUPP; 347 } 348 349 return 0; 350 } 351 352 static void *uapi_get_attr_for_method(struct bundle_priv *pbundle, 353 u32 attr_key) 354 { 355 return radix_tree_lookup(pbundle->radix, 356 pbundle->method_key | attr_key); 357 } 358 359 static int uverbs_set_attr(struct bundle_priv *pbundle, 360 struct ib_uverbs_attr *uattr) 361 { 362 u32 attr_key = uapi_key_attr(uattr->attr_id); 363 u32 attr_bkey = uapi_bkey_attr(attr_key); 364 const struct uverbs_api_attr *attr; 365 void *slot; 366 int ret; 367 368 slot = uapi_get_attr_for_method(pbundle, attr_key); 369 if (!slot) { 370 /* 371 * Kernel does not support the attribute but user-space says it 372 * is mandatory 373 */ 374 if (uattr->flags & UVERBS_ATTR_F_MANDATORY) 375 return -EPROTONOSUPPORT; 376 return 0; 377 } 378 attr = slot; 379 380 /* Reject duplicate attributes from user-space */ 381 if (test_bit(attr_bkey, pbundle->bundle.attr_present)) 382 return -EINVAL; 383 384 ret = uverbs_process_attr(pbundle, attr, uattr, attr_bkey); 385 if (ret) 386 return ret; 387 388 __set_bit(attr_bkey, pbundle->bundle.attr_present); 389 390 return 0; 391 } 392 393 static int ib_uverbs_run_method(struct bundle_priv *pbundle, 394 unsigned int num_attrs) 395 { 396 int (*handler)(struct uverbs_attr_bundle *attrs); 397 size_t uattrs_size = array_size(sizeof(*pbundle->uattrs), num_attrs); 398 unsigned int destroy_bkey = pbundle->method_elm->destroy_bkey; 399 unsigned int i; 400 int ret; 401 402 /* See uverbs_disassociate_api() */ 403 handler = srcu_dereference( 404 pbundle->method_elm->handler, 405 &pbundle->bundle.ufile->device->disassociate_srcu); 406 if (!handler) 407 return -EIO; 408 409 pbundle->uattrs = uverbs_alloc(&pbundle->bundle, uattrs_size); 410 if (IS_ERR(pbundle->uattrs)) 411 return PTR_ERR(pbundle->uattrs); 412 if (copy_from_user(pbundle->uattrs, pbundle->user_attrs, uattrs_size)) 413 return -EFAULT; 414 415 for (i = 0; i != num_attrs; i++) { 416 ret = uverbs_set_attr(pbundle, &pbundle->uattrs[i]); 417 if (unlikely(ret)) 418 return ret; 419 } 420 421 /* User space did not provide all the mandatory attributes */ 422 if (unlikely(!bitmap_subset(pbundle->method_elm->attr_mandatory, 423 pbundle->bundle.attr_present, 424 pbundle->method_elm->key_bitmap_len))) 425 return -EINVAL; 426 427 if (pbundle->method_elm->has_udata) 428 uverbs_fill_udata(&pbundle->bundle, 429 &pbundle->bundle.driver_udata, 430 UVERBS_ATTR_UHW_IN, UVERBS_ATTR_UHW_OUT); 431 else 432 pbundle->bundle.driver_udata = (struct ib_udata){}; 433 434 if (destroy_bkey != UVERBS_API_ATTR_BKEY_LEN) { 435 struct uverbs_obj_attr *destroy_attr = 436 &pbundle->bundle.attrs[destroy_bkey].obj_attr; 437 438 ret = uobj_destroy(destroy_attr->uobject, &pbundle->bundle); 439 if (ret) 440 return ret; 441 __clear_bit(destroy_bkey, pbundle->uobj_finalize); 442 443 ret = handler(&pbundle->bundle); 444 uobj_put_destroy(destroy_attr->uobject); 445 } else { 446 ret = handler(&pbundle->bundle); 447 } 448 449 /* 450 * Until the drivers are revised to use the bundle directly we have to 451 * assume that the driver wrote to its UHW_OUT and flag userspace 452 * appropriately. 453 */ 454 if (!ret && pbundle->method_elm->has_udata) { 455 const struct uverbs_attr *attr = 456 uverbs_attr_get(&pbundle->bundle, UVERBS_ATTR_UHW_OUT); 457 458 if (!IS_ERR(attr)) 459 ret = uverbs_set_output(&pbundle->bundle, attr); 460 } 461 462 /* 463 * EPROTONOSUPPORT is ONLY to be returned if the ioctl framework can 464 * not invoke the method because the request is not supported. No 465 * other cases should return this code. 466 */ 467 if (WARN_ON_ONCE(ret == -EPROTONOSUPPORT)) 468 return -EINVAL; 469 470 return ret; 471 } 472 473 static void bundle_destroy(struct bundle_priv *pbundle, bool commit) 474 { 475 unsigned int key_bitmap_len = pbundle->method_elm->key_bitmap_len; 476 struct bundle_alloc_head *memblock; 477 unsigned int i; 478 479 /* fast path for simple uobjects */ 480 i = -1; 481 while ((i = find_next_bit(pbundle->uobj_finalize, key_bitmap_len, 482 i + 1)) < key_bitmap_len) { 483 struct uverbs_attr *attr = &pbundle->bundle.attrs[i]; 484 485 uverbs_finalize_object( 486 attr->obj_attr.uobject, 487 attr->obj_attr.attr_elm->spec.u.obj.access, commit, 488 &pbundle->bundle); 489 } 490 491 i = -1; 492 while ((i = find_next_bit(pbundle->spec_finalize, key_bitmap_len, 493 i + 1)) < key_bitmap_len) { 494 struct uverbs_attr *attr = &pbundle->bundle.attrs[i]; 495 const struct uverbs_api_attr *attr_uapi; 496 void *slot; 497 498 slot = uapi_get_attr_for_method( 499 pbundle, 500 pbundle->method_key | uapi_bkey_to_key_attr(i)); 501 if (WARN_ON(!slot)) 502 continue; 503 504 attr_uapi = slot; 505 506 if (attr_uapi->spec.type == UVERBS_ATTR_TYPE_IDRS_ARRAY) { 507 uverbs_free_idrs_array(attr_uapi, &attr->objs_arr_attr, 508 commit, &pbundle->bundle); 509 } 510 } 511 512 for (memblock = pbundle->allocated_mem; memblock;) { 513 struct bundle_alloc_head *tmp = memblock; 514 515 memblock = memblock->next; 516 kvfree(tmp); 517 } 518 } 519 520 static int ib_uverbs_cmd_verbs(struct ib_uverbs_file *ufile, 521 struct ib_uverbs_ioctl_hdr *hdr, 522 struct ib_uverbs_attr __user *user_attrs) 523 { 524 const struct uverbs_api_ioctl_method *method_elm; 525 struct uverbs_api *uapi = ufile->device->uapi; 526 struct bundle_priv *pbundle; 527 struct bundle_priv onstack; 528 void *slot; 529 int ret; 530 531 if (unlikely(hdr->driver_id != uapi->driver_id)) 532 return -EINVAL; 533 534 slot = radix_tree_lookup( 535 &uapi->radix, 536 uapi_key_obj(hdr->object_id) | 537 uapi_key_ioctl_method(hdr->method_id)); 538 if (unlikely(!slot)) 539 return -EPROTONOSUPPORT; 540 method_elm = slot; 541 542 if (!method_elm->use_stack) { 543 pbundle = kmalloc(method_elm->bundle_size, GFP_KERNEL); 544 if (!pbundle) 545 return -ENOMEM; 546 pbundle->internal_avail = 547 method_elm->bundle_size - 548 offsetof(struct bundle_priv, internal_buffer); 549 pbundle->alloc_head.next = NULL; 550 pbundle->allocated_mem = &pbundle->alloc_head; 551 } else { 552 pbundle = &onstack; 553 pbundle->internal_avail = sizeof(pbundle->internal_buffer); 554 pbundle->allocated_mem = NULL; 555 } 556 557 /* Space for the pbundle->bundle.attrs flex array */ 558 pbundle->method_elm = method_elm; 559 pbundle->method_key = 560 uapi_key_obj(hdr->object_id) | 561 uapi_key_ioctl_method(hdr->method_id); 562 pbundle->bundle.ufile = ufile; 563 pbundle->bundle.context = NULL; /* only valid if bundle has uobject */ 564 pbundle->radix = &uapi->radix; 565 pbundle->user_attrs = user_attrs; 566 567 pbundle->internal_used = ALIGN(pbundle->method_elm->key_bitmap_len * 568 sizeof(*pbundle->bundle.attrs), 569 sizeof(*pbundle->internal_buffer)); 570 memset(pbundle->bundle.attr_present, 0, 571 sizeof(pbundle->bundle.attr_present)); 572 memset(pbundle->uobj_finalize, 0, sizeof(pbundle->uobj_finalize)); 573 memset(pbundle->spec_finalize, 0, sizeof(pbundle->spec_finalize)); 574 575 ret = ib_uverbs_run_method(pbundle, hdr->num_attrs); 576 bundle_destroy(pbundle, ret == 0); 577 return ret; 578 } 579 580 long ib_uverbs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 581 { 582 struct ib_uverbs_file *file = filp->private_data; 583 struct ib_uverbs_ioctl_hdr __user *user_hdr = 584 (struct ib_uverbs_ioctl_hdr __user *)arg; 585 struct ib_uverbs_ioctl_hdr hdr; 586 int srcu_key; 587 int err; 588 589 if (unlikely(cmd != RDMA_VERBS_IOCTL)) 590 return -ENOIOCTLCMD; 591 592 err = copy_from_user(&hdr, user_hdr, sizeof(hdr)); 593 if (err) 594 return -EFAULT; 595 596 if (hdr.length > PAGE_SIZE || 597 hdr.length != struct_size(&hdr, attrs, hdr.num_attrs)) 598 return -EINVAL; 599 600 if (hdr.reserved1 || hdr.reserved2) 601 return -EPROTONOSUPPORT; 602 603 srcu_key = srcu_read_lock(&file->device->disassociate_srcu); 604 err = ib_uverbs_cmd_verbs(file, &hdr, user_hdr->attrs); 605 srcu_read_unlock(&file->device->disassociate_srcu, srcu_key); 606 return err; 607 } 608 609 int uverbs_get_flags64(u64 *to, const struct uverbs_attr_bundle *attrs_bundle, 610 size_t idx, u64 allowed_bits) 611 { 612 const struct uverbs_attr *attr; 613 u64 flags; 614 615 attr = uverbs_attr_get(attrs_bundle, idx); 616 /* Missing attribute means 0 flags */ 617 if (IS_ERR(attr)) { 618 *to = 0; 619 return 0; 620 } 621 622 /* 623 * New userspace code should use 8 bytes to pass flags, but we 624 * transparently support old userspaces that were using 4 bytes as 625 * well. 626 */ 627 if (attr->ptr_attr.len == 8) 628 flags = attr->ptr_attr.data; 629 else if (attr->ptr_attr.len == 4) 630 flags = *(const u32 *)&attr->ptr_attr.data; 631 else 632 return -EINVAL; 633 634 if (flags & ~allowed_bits) 635 return -EINVAL; 636 637 *to = flags; 638 return 0; 639 } 640 EXPORT_SYMBOL(uverbs_get_flags64); 641 642 int uverbs_get_flags32(u32 *to, const struct uverbs_attr_bundle *attrs_bundle, 643 size_t idx, u64 allowed_bits) 644 { 645 u64 flags; 646 int ret; 647 648 ret = uverbs_get_flags64(&flags, attrs_bundle, idx, allowed_bits); 649 if (ret) 650 return ret; 651 652 if (flags > U32_MAX) 653 return -EINVAL; 654 *to = flags; 655 656 return 0; 657 } 658 EXPORT_SYMBOL(uverbs_get_flags32); 659 660 /* 661 * Fill a ib_udata struct (core or uhw) using the given attribute IDs. 662 * This is primarily used to convert the UVERBS_ATTR_UHW() into the 663 * ib_udata format used by the drivers. 664 */ 665 void uverbs_fill_udata(struct uverbs_attr_bundle *bundle, 666 struct ib_udata *udata, unsigned int attr_in, 667 unsigned int attr_out) 668 { 669 struct bundle_priv *pbundle = 670 container_of(bundle, struct bundle_priv, bundle); 671 const struct uverbs_attr *in = 672 uverbs_attr_get(&pbundle->bundle, attr_in); 673 const struct uverbs_attr *out = 674 uverbs_attr_get(&pbundle->bundle, attr_out); 675 676 if (!IS_ERR(in)) { 677 udata->inlen = in->ptr_attr.len; 678 if (uverbs_attr_ptr_is_inline(in)) 679 udata->inbuf = (void *) 680 &pbundle->user_attrs[in->ptr_attr.uattr_idx] 681 .data; 682 else 683 udata->inbuf = u64_to_user_ptr(in->ptr_attr.data); 684 } else { 685 udata->inbuf = NULL; 686 udata->inlen = 0; 687 } 688 689 if (!IS_ERR(out)) { 690 udata->outbuf = u64_to_user_ptr(out->ptr_attr.data); 691 udata->outlen = out->ptr_attr.len; 692 } else { 693 udata->outbuf = NULL; 694 udata->outlen = 0; 695 } 696 } 697 698 int uverbs_copy_to(const struct uverbs_attr_bundle *bundle, size_t idx, 699 const void *from, size_t size) 700 { 701 const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx); 702 size_t min_size; 703 704 if (IS_ERR(attr)) 705 return PTR_ERR(attr); 706 707 min_size = min_t(size_t, attr->ptr_attr.len, size); 708 if (copy_to_user(u64_to_user_ptr(attr->ptr_attr.data), from, min_size)) 709 return -EFAULT; 710 711 return uverbs_set_output(bundle, attr); 712 } 713 EXPORT_SYMBOL(uverbs_copy_to); 714 715 716 /* 717 * This is only used if the caller has directly used copy_to_use to write the 718 * data. It signals to user space that the buffer is filled in. 719 */ 720 int uverbs_output_written(const struct uverbs_attr_bundle *bundle, size_t idx) 721 { 722 const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx); 723 724 if (IS_ERR(attr)) 725 return PTR_ERR(attr); 726 727 return uverbs_set_output(bundle, attr); 728 } 729 730 int _uverbs_get_const(s64 *to, const struct uverbs_attr_bundle *attrs_bundle, 731 size_t idx, s64 lower_bound, u64 upper_bound, 732 s64 *def_val) 733 { 734 const struct uverbs_attr *attr; 735 736 attr = uverbs_attr_get(attrs_bundle, idx); 737 if (IS_ERR(attr)) { 738 if ((PTR_ERR(attr) != -ENOENT) || !def_val) 739 return PTR_ERR(attr); 740 741 *to = *def_val; 742 } else { 743 *to = attr->ptr_attr.data; 744 } 745 746 if (*to < lower_bound || (*to > 0 && (u64)*to > upper_bound)) 747 return -EINVAL; 748 749 return 0; 750 } 751 EXPORT_SYMBOL(_uverbs_get_const); 752 753 int uverbs_copy_to_struct_or_zero(const struct uverbs_attr_bundle *bundle, 754 size_t idx, const void *from, size_t size) 755 { 756 const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx); 757 758 if (IS_ERR(attr)) 759 return PTR_ERR(attr); 760 761 if (size < attr->ptr_attr.len) { 762 if (clear_user(u64_to_user_ptr(attr->ptr_attr.data + size), 763 attr->ptr_attr.len - size)) 764 return -EFAULT; 765 } 766 return uverbs_copy_to(bundle, idx, from, size); 767 } 768