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

RDMA/uverbs: Avoid -Wflex-array-member-not-at-end warnings

-Wflex-array-member-not-at-end is coming in GCC-14, and we are getting
ready to enable it globally.

There are currently a couple of objects (`alloc_head` and `bundle`) in
`struct bundle_priv` that contain a couple of flexible structures:

struct bundle_priv {
/* Must be first */
struct bundle_alloc_head alloc_head;

...

/*
* Must be last. bundle ends in a flex array which overlaps
* internal_buffer.
*/
struct uverbs_attr_bundle bundle;
u64 internal_buffer[32];
};

So, in order to avoid ending up with a couple of flexible-array members
in the middle of a struct, we use the `struct_group_tagged()` helper to
separate the flexible array from the rest of the members in the flexible
structures:

struct uverbs_attr_bundle {
struct_group_tagged(uverbs_attr_bundle_hdr, hdr,
... the rest of the members
);
struct uverbs_attr attrs[];
};

With the change described above, we now declare objects of the type of
the tagged struct without embedding flexible arrays in the middle of
another struct:

struct bundle_priv {
/* Must be first */
struct bundle_alloc_head_hdr alloc_head;

...

struct uverbs_attr_bundle_hdr bundle;
u64 internal_buffer[32];
};

We also use `container_of()` whenever we need to retrieve a pointer
to the flexible structures.

Notice that the `bundle_size` computed in `uapi_compute_bundle_size()`
remains the same.

So, with these changes, fix the following warnings:

drivers/infiniband/core/uverbs_ioctl.c:45:34: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
45 | struct bundle_alloc_head alloc_head;
| ^~~~~~~~~~
drivers/infiniband/core/uverbs_ioctl.c:67:35: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
67 | struct uverbs_attr_bundle bundle;
| ^~~~~~

Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
Link: https://lore.kernel.org/r/ZeIgeZ5Sb0IZTOyt@neat
Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Leon Romanovsky <leon@kernel.org>

authored by

Gustavo A. R. Silva and committed by
Leon Romanovsky
155f0436 6ec429d5

+53 -39
+45 -33
drivers/infiniband/core/uverbs_ioctl.c
··· 36 36 #include "uverbs.h" 37 37 38 38 struct bundle_alloc_head { 39 - struct bundle_alloc_head *next; 39 + struct_group_tagged(bundle_alloc_head_hdr, hdr, 40 + struct bundle_alloc_head *next; 41 + ); 40 42 u8 data[]; 41 43 }; 42 44 43 45 struct bundle_priv { 44 46 /* Must be first */ 45 - struct bundle_alloc_head alloc_head; 47 + struct bundle_alloc_head_hdr alloc_head; 46 48 struct bundle_alloc_head *allocated_mem; 47 49 size_t internal_avail; 48 50 size_t internal_used; ··· 66 64 * Must be last. bundle ends in a flex array which overlaps 67 65 * internal_buffer. 68 66 */ 69 - struct uverbs_attr_bundle bundle; 67 + struct uverbs_attr_bundle_hdr bundle; 70 68 u64 internal_buffer[32]; 71 69 }; 72 70 ··· 79 77 unsigned int num_attrs) 80 78 { 81 79 struct bundle_priv *pbundle; 80 + struct uverbs_attr_bundle *bundle; 82 81 size_t bundle_size = 83 82 offsetof(struct bundle_priv, internal_buffer) + 84 - sizeof(*pbundle->bundle.attrs) * method_elm->key_bitmap_len + 83 + sizeof(*bundle->attrs) * method_elm->key_bitmap_len + 85 84 sizeof(*pbundle->uattrs) * num_attrs; 86 85 87 86 method_elm->use_stack = bundle_size <= sizeof(*pbundle); ··· 110 107 gfp_t flags) 111 108 { 112 109 struct bundle_priv *pbundle = 113 - container_of(bundle, struct bundle_priv, bundle); 110 + container_of(&bundle->hdr, struct bundle_priv, bundle); 114 111 size_t new_used; 115 112 void *res; 116 113 ··· 152 149 const struct uverbs_attr *attr) 153 150 { 154 151 struct bundle_priv *pbundle = 155 - container_of(bundle, struct bundle_priv, bundle); 152 + container_of(&bundle->hdr, struct bundle_priv, bundle); 156 153 u16 flags; 157 154 158 155 flags = pbundle->uattrs[attr->ptr_attr.uattr_idx].flags | ··· 169 166 struct ib_uverbs_attr *uattr, 170 167 u32 attr_bkey) 171 168 { 169 + struct uverbs_attr_bundle *bundle = 170 + container_of(&pbundle->bundle, struct uverbs_attr_bundle, hdr); 172 171 const struct uverbs_attr_spec *spec = &attr_uapi->spec; 173 172 size_t array_len; 174 173 u32 *idr_vals; ··· 189 184 return -EINVAL; 190 185 191 186 attr->uobjects = 192 - uverbs_alloc(&pbundle->bundle, 187 + uverbs_alloc(bundle, 193 188 array_size(array_len, sizeof(*attr->uobjects))); 194 189 if (IS_ERR(attr->uobjects)) 195 190 return PTR_ERR(attr->uobjects); ··· 214 209 for (i = 0; i != array_len; i++) { 215 210 attr->uobjects[i] = uverbs_get_uobject_from_file( 216 211 spec->u2.objs_arr.obj_type, spec->u2.objs_arr.access, 217 - idr_vals[i], &pbundle->bundle); 212 + idr_vals[i], bundle); 218 213 if (IS_ERR(attr->uobjects[i])) { 219 214 ret = PTR_ERR(attr->uobjects[i]); 220 215 break; ··· 245 240 struct ib_uverbs_attr *uattr, u32 attr_bkey) 246 241 { 247 242 const struct uverbs_attr_spec *spec = &attr_uapi->spec; 248 - struct uverbs_attr *e = &pbundle->bundle.attrs[attr_bkey]; 243 + struct uverbs_attr_bundle *bundle = 244 + container_of(&pbundle->bundle, struct uverbs_attr_bundle, hdr); 245 + struct uverbs_attr *e = &bundle->attrs[attr_bkey]; 249 246 const struct uverbs_attr_spec *val_spec = spec; 250 247 struct uverbs_obj_attr *o_attr; 251 248 ··· 295 288 if (val_spec->alloc_and_copy && !uverbs_attr_ptr_is_inline(e)) { 296 289 void *p; 297 290 298 - p = uverbs_alloc(&pbundle->bundle, uattr->len); 291 + p = uverbs_alloc(bundle, uattr->len); 299 292 if (IS_ERR(p)) 300 293 return PTR_ERR(p); 301 294 ··· 328 321 */ 329 322 o_attr->uobject = uverbs_get_uobject_from_file( 330 323 spec->u.obj.obj_type, spec->u.obj.access, 331 - uattr->data_s64, &pbundle->bundle); 324 + uattr->data_s64, bundle); 332 325 if (IS_ERR(o_attr->uobject)) 333 326 return PTR_ERR(o_attr->uobject); 334 327 __set_bit(attr_bkey, pbundle->uobj_finalize); ··· 429 422 unsigned int num_attrs) 430 423 { 431 424 int (*handler)(struct uverbs_attr_bundle *attrs); 425 + struct uverbs_attr_bundle *bundle = 426 + container_of(&pbundle->bundle, struct uverbs_attr_bundle, hdr); 432 427 size_t uattrs_size = array_size(sizeof(*pbundle->uattrs), num_attrs); 433 428 unsigned int destroy_bkey = pbundle->method_elm->destroy_bkey; 434 429 unsigned int i; ··· 443 434 if (!handler) 444 435 return -EIO; 445 436 446 - pbundle->uattrs = uverbs_alloc(&pbundle->bundle, uattrs_size); 437 + pbundle->uattrs = uverbs_alloc(bundle, uattrs_size); 447 438 if (IS_ERR(pbundle->uattrs)) 448 439 return PTR_ERR(pbundle->uattrs); 449 440 if (copy_from_user(pbundle->uattrs, pbundle->user_attrs, uattrs_size)) ··· 462 453 return -EINVAL; 463 454 464 455 if (pbundle->method_elm->has_udata) 465 - uverbs_fill_udata(&pbundle->bundle, 466 - &pbundle->bundle.driver_udata, 456 + uverbs_fill_udata(bundle, &pbundle->bundle.driver_udata, 467 457 UVERBS_ATTR_UHW_IN, UVERBS_ATTR_UHW_OUT); 468 458 else 469 459 pbundle->bundle.driver_udata = (struct ib_udata){}; 470 460 471 461 if (destroy_bkey != UVERBS_API_ATTR_BKEY_LEN) { 472 - struct uverbs_obj_attr *destroy_attr = 473 - &pbundle->bundle.attrs[destroy_bkey].obj_attr; 462 + struct uverbs_obj_attr *destroy_attr = &bundle->attrs[destroy_bkey].obj_attr; 474 463 475 - ret = uobj_destroy(destroy_attr->uobject, &pbundle->bundle); 464 + ret = uobj_destroy(destroy_attr->uobject, bundle); 476 465 if (ret) 477 466 return ret; 478 467 __clear_bit(destroy_bkey, pbundle->uobj_finalize); 479 468 480 - ret = handler(&pbundle->bundle); 469 + ret = handler(bundle); 481 470 uobj_put_destroy(destroy_attr->uobject); 482 471 } else { 483 - ret = handler(&pbundle->bundle); 472 + ret = handler(bundle); 484 473 } 485 474 486 475 /* ··· 488 481 */ 489 482 if (!ret && pbundle->method_elm->has_udata) { 490 483 const struct uverbs_attr *attr = 491 - uverbs_attr_get(&pbundle->bundle, UVERBS_ATTR_UHW_OUT); 484 + uverbs_attr_get(bundle, UVERBS_ATTR_UHW_OUT); 492 485 493 486 if (!IS_ERR(attr)) 494 - ret = uverbs_set_output(&pbundle->bundle, attr); 487 + ret = uverbs_set_output(bundle, attr); 495 488 } 496 489 497 490 /* ··· 508 501 static void bundle_destroy(struct bundle_priv *pbundle, bool commit) 509 502 { 510 503 unsigned int key_bitmap_len = pbundle->method_elm->key_bitmap_len; 504 + struct uverbs_attr_bundle *bundle = 505 + container_of(&pbundle->bundle, struct uverbs_attr_bundle, hdr); 511 506 struct bundle_alloc_head *memblock; 512 507 unsigned int i; 513 508 ··· 517 508 i = -1; 518 509 while ((i = find_next_bit(pbundle->uobj_finalize, key_bitmap_len, 519 510 i + 1)) < key_bitmap_len) { 520 - struct uverbs_attr *attr = &pbundle->bundle.attrs[i]; 511 + struct uverbs_attr *attr = &bundle->attrs[i]; 521 512 522 513 uverbs_finalize_object( 523 514 attr->obj_attr.uobject, 524 515 attr->obj_attr.attr_elm->spec.u.obj.access, 525 516 test_bit(i, pbundle->uobj_hw_obj_valid), 526 - commit, 527 - &pbundle->bundle); 517 + commit, bundle); 528 518 } 529 519 530 520 i = -1; 531 521 while ((i = find_next_bit(pbundle->spec_finalize, key_bitmap_len, 532 522 i + 1)) < key_bitmap_len) { 533 - struct uverbs_attr *attr = &pbundle->bundle.attrs[i]; 523 + struct uverbs_attr *attr = &bundle->attrs[i]; 534 524 const struct uverbs_api_attr *attr_uapi; 535 525 void __rcu **slot; 536 526 ··· 543 535 544 536 if (attr_uapi->spec.type == UVERBS_ATTR_TYPE_IDRS_ARRAY) { 545 537 uverbs_free_idrs_array(attr_uapi, &attr->objs_arr_attr, 546 - commit, &pbundle->bundle); 538 + commit, bundle); 547 539 } 548 540 } 549 541 ··· 586 578 method_elm->bundle_size - 587 579 offsetof(struct bundle_priv, internal_buffer); 588 580 pbundle->alloc_head.next = NULL; 589 - pbundle->allocated_mem = &pbundle->alloc_head; 581 + pbundle->allocated_mem = container_of(&pbundle->alloc_head, 582 + struct bundle_alloc_head, hdr); 590 583 } else { 591 584 pbundle = &onstack; 592 585 pbundle->internal_avail = sizeof(pbundle->internal_buffer); ··· 605 596 pbundle->user_attrs = user_attrs; 606 597 607 598 pbundle->internal_used = ALIGN(pbundle->method_elm->key_bitmap_len * 608 - sizeof(*pbundle->bundle.attrs), 609 - sizeof(*pbundle->internal_buffer)); 599 + sizeof(*container_of(&pbundle->bundle, 600 + struct uverbs_attr_bundle, hdr)->attrs), 601 + sizeof(*pbundle->internal_buffer)); 610 602 memset(pbundle->bundle.attr_present, 0, 611 603 sizeof(pbundle->bundle.attr_present)); 612 604 memset(pbundle->uobj_finalize, 0, sizeof(pbundle->uobj_finalize)); ··· 710 700 unsigned int attr_out) 711 701 { 712 702 struct bundle_priv *pbundle = 713 - container_of(bundle, struct bundle_priv, bundle); 703 + container_of(&bundle->hdr, struct bundle_priv, bundle); 704 + struct uverbs_attr_bundle *bundle_aux = 705 + container_of(&pbundle->bundle, struct uverbs_attr_bundle, hdr); 714 706 const struct uverbs_attr *in = 715 - uverbs_attr_get(&pbundle->bundle, attr_in); 707 + uverbs_attr_get(bundle_aux, attr_in); 716 708 const struct uverbs_attr *out = 717 - uverbs_attr_get(&pbundle->bundle, attr_out); 709 + uverbs_attr_get(bundle_aux, attr_out); 718 710 719 711 if (!IS_ERR(in)) { 720 712 udata->inlen = in->ptr_attr.len; ··· 841 829 u16 idx) 842 830 { 843 831 struct bundle_priv *pbundle = 844 - container_of(bundle, struct bundle_priv, bundle); 832 + container_of(&bundle->hdr, struct bundle_priv, bundle); 845 833 846 834 __set_bit(uapi_bkey_attr(uapi_key_attr(idx)), 847 835 pbundle->uobj_hw_obj_valid);
+8 -6
include/rdma/uverbs_ioctl.h
··· 629 629 }; 630 630 631 631 struct uverbs_attr_bundle { 632 - struct ib_udata driver_udata; 633 - struct ib_udata ucore; 634 - struct ib_uverbs_file *ufile; 635 - struct ib_ucontext *context; 636 - struct ib_uobject *uobject; 637 - DECLARE_BITMAP(attr_present, UVERBS_API_ATTR_BKEY_LEN); 632 + struct_group_tagged(uverbs_attr_bundle_hdr, hdr, 633 + struct ib_udata driver_udata; 634 + struct ib_udata ucore; 635 + struct ib_uverbs_file *ufile; 636 + struct ib_ucontext *context; 637 + struct ib_uobject *uobject; 638 + DECLARE_BITMAP(attr_present, UVERBS_API_ATTR_BKEY_LEN); 639 + ); 638 640 struct uverbs_attr attrs[]; 639 641 }; 640 642