On Fri, Jul 17, 2026 at 4:19 PM Gustavo A. R. Silva
<[email protected]> wrote:
>
> Hi!
>
> On 7/17/26 10:17, Jesse Taube wrote:
> > On Wed, Jul 15, 2026 at 12:12 PM Kees Cook <[email protected]> wrote:
> >>
> >> On Tue, Jul 14, 2026 at 11:18:18AM -0400, Jesse Taube wrote:
> >>> Add new DECLARE_SIZED_FLEX() helper to set the default size of a
> >>> flexible-array member. The code is identical to the declaration in
> >>> __DEFINE_FLEX() which has also been changed to use DECLARE_SIZED_FLEX().
> >>>
> >>> Add DECLARE_COUNTED_FLEX_ARRAY() helper which is a variant of
> >>> DECLARE_FLEX_ARRAY() with a counted-by attribute.
> >>>
> >>> Also add default sized variants of
> >>> DECLARE_FLEX_ARRAY(), DECLARE_SIZED_FLEX(), and
> >>> DECLARE_COUNTED_FLEX_ARRAY(), DECLARE_COUNTED_SIZED_FLEX().
> >>
> >> Where do you want to use these new helpers?
> >>
> >>> Signed-off-by: Jesse Taube <[email protected]>
> >>> ---
> >>> include/linux/overflow.h | 58 +++++++++++++++++++++++++++++++++++++---
> >>> 1 file changed, 54 insertions(+), 4 deletions(-)
> >>>
> >>> diff --git a/include/linux/overflow.h b/include/linux/overflow.h
> >>> index a8cb6319b4fb..a3384cae49e5 100644
> >>> --- a/include/linux/overflow.h
> >>> +++ b/include/linux/overflow.h
> >>> @@ -464,6 +464,59 @@ static __always_inline size_t __must_check
> >>> size_sub(size_t minuend, size_t subtr
> >>> */
> >>> #define struct_offset(p, member) (offsetof(typeof(*(p)), member))
> >>>
> >>> +/**
> >>> + * __DECLARE_SIZED_FLEX() - helper macro for DECLARE_SIZED_FLEX() family.
> >>> + * Allows for easily declaring a structure with a trailing flexible
> >>> array member
> >>> + * to have a specific size.
> >>> + *
> >>> + * @obj: object to be given a specific size
> >>> + * @name: Name of the array member.
> >>> + * @count: Number of elements in the array; must be compile-time const.
> >>> + */
> >>> +#define __DECLARE_SIZED_FLEX(obj, name, count) \
> >>> + _Static_assert(__builtin_constant_p(count), \
> >>> + "default sized flex array members require
> >>> compile-time const count"); \
> >>> + union { \
> >>> + u8 bytes[struct_size_t(obj, name, count)]; \
> >>> + obj; \
> >>> + }
> >>> +
> >>> +/**
> >>> + * DECLARE_COUNTED_FLEX_ARRAY() - Declare a counted flexible array
> >>> + *
> >>> + * @type: Type name.
> >>> + * @name: Name of the array member.
> >>> + * @counter: Name of the __counted_by member.
> >>> + */
> >>> +#define DECLARE_COUNTED_FLEX_ARRAY(type, name, counter)\
> >>> + struct { \
> >>> + size_t counter; \
> >>> + type name[] __counted_by(counter); \
> >>> + }
> >>> +
> >>> +/**
> >>> + * DECLARE_SIZED_FLEX() - Declare a structure with a trailing flexible
> >>> array
> >>> + * member with a default size.
> >>> + *
> >>> + * @type: Type name.
> >>> + * @name: Name of the array member.
> >>> + * @count: Number of elements in the array; must be compile-time const.
> >>> + */
> >>> +#define DECLARE_SIZED_FLEX(type, name, count) \
> >>> + __DECLARE_SIZED_FLEX(type name[], name, count)
> >>> +
> >>> +/**
> >>> + * DECLARE_COUNTED_SIZED_FLEX() - Declare a structure with a trailing
> >>> flexible
> >>> + * array member counted by count, with a default size.
> >>> + *
> >>> + * @type: Type name.
> >>> + * @name: Name of the array member.
> >>> + * @counter: Name of the __counted_by member.
> >>> + * @count: Number of elements in the array; must be compile-time const.
> >>> + */
> >>> +#define DECLARE_COUNTED_SIZED_FLEX(type, name, counter, count) \
> >>> + __DECLARE_SIZED_FLEX(DECLARE_COUNTED_FLEX_ARRAY(type, name,
> >>> counter), name, count)
> >>
> >> I ask about where these will be used because one of the things I want to
> >> keep tied together is the "counter" and "count", which usually means the
> >> declaration should be combined with an initializer in some way so that
> >> the counter gets assigned, as DEFINE_FLEX() ultimately does.
> >>
> >> I'm worried that extracting the internal construction of __DEFINE_FLEX
> >> means we may run the risk of increasing the risk of losing that tie.
> >
> > We can add a comment to make sure to set count, or use DEFINE_FLEX
> > to allocate it. Im not sure if there is a way for this to be a compile time
> > error though.
> >
> >> So, I'd love to understand how you want to use this, as that would help
> >> my understanding and potentially shape the design so we can keep counter
> >> and count strongly associated.
> >
> > Basically, I want to use `DECLARE_COUNTED_SIZED_FLEX` for a version of
> > this patch that
> > uses `__counted_by`
> > https://lore.kernel.org/linux-scsi/[email protected]/
> > I have checked that it does always set the `counter` variable correctly.
> >
> > As for `DECLARE_COUNTED_FLEX_ARRAY` there is already `DECLARE_FLEX_ARRAY`
> > and
> > the counted variant is already used in a few places. A good example is
> > `struct max77759_maxq_response` which subsiqently gets allocated with
> > `DEFINE_FLEX`
> > https://elixir.bootlin.com/linux/v7.2-rc1/source/include/linux/mfd/max77759.h#L253
> >
> > I assume you are ok with adding `__DECLARE_SIZED_FLEX` and
> > `DECLARE_SIZED_FLEX` as
> > they are usefull in cases where keeping structure offsets is
> > important, similar to
> > TRAILING_OVERLAP. An example of where `__DECLARE_SIZED_FLEX` could be used
> > is:
> > https://lore.kernel.org/all/[email protected]/
>
> Please show us examples of how exactly you'd use the helpers you propose
> for the cases you mentioned above.
Sorry for the late reply.
Here is an example of DECLARE_COUNTED_FLEX_ARRAY,
I notice now that the macro should be passed the count variable's type
and not have it as size_t.
```c
+++ b/drivers/net/wireless/ath/ath10k/bmi.h
@@ -136,21 +136,12 @@ struct bmi_cmd {
struct {
__le32 patch_id;
} rompatch_uninstall;
- struct {
- __le32 count;
- __le32 patch_ids[]; /* length of @count */
- } rompatch_activate;
- struct {
- __le32 count;
- __le32 patch_ids[]; /* length of @count */
- } rompatch_deactivate;
+ DECLARE_COUNTED_FLEX_ARRAY(__le32, patch_ids, count)
rompatch_activate;
+ DECLARE_COUNTED_FLEX_ARRAY(__le32, patch_ids, count)
rompatch_deactivate;
struct {
__le32 addr;
} lz_start;
- struct {
- __le32 len; /* max BMI_MAX_DATA_SIZE */
- u8 payload[]; /* length of @len */
- } lz_data;
+ DECLARE_COUNTED_FLEX_ARRAY(u8, payload, len) lz_data;
struct {
u8 name[BMI_NVRAM_SEG_NAME_SZ];
} nvram_process;
```
Here is where i want to use DECLARE_COUNTED_SIZED_FLEX, it would fix the
"memcpy: detected field-spanning write (size 60) of single field".
It seems like the only two places where a structure like this occurs is in
qla2xxx and qla4xxx
https://lore.kernel.org/linux-scsi/[email protected]/
```c
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 5593ad7fad27..7241cf6e6c7e 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -4912,10 +4912,7 @@ struct purex_item {
void (*process_item)(struct scsi_qla_host *vha,
struct purex_item *pkt);
atomic_t in_use;
- uint16_t size;
- struct {
- uint8_t iocb[64];
- } iocb;
+ DECLARE_COUNTED_SIZED_FLEX(uint8_t, iocb, size, 64);
};
```
Here is an example of DECLARE_SIZED_FLEX:
```c
#define DEFUALT_SIZE 64
struct flex_array {
int some_element;
DECLARE_SIZED_FLEX(uint8_t, payload, DEFUALT_SIZE);
};
struct struct_with_flex_array {
int some_element;
struct flex_array flex_array;
};
int main() {
struct struct_with_flex_array my_struct;
struct flex_array *my_struct2;
uint8_t big_payload[100] = {};
/* Size of struct_with_flex_array: 72*/
printf("Size of struct_with_flex_array: %zu\n", sizeof(my_struct));
/* kzalloc_flex would need the size to be (sizeof(big_payload) -
DEFUALT_SIZE) */
my_struct2 = kzalloc(sizeof(*my_struct2) + sizeof(big_payload) -
DEFUALT_SIZE, GFP_KERNEL);
/* Size of allocated flex_array: 104 */
printf("Size of allocated flex_array: %zu\n", sizeof(*my_struct2) +
sizeof(big_payload) - DEFUALT_SIZE);
/* Avoids "memcpy: detected field-spanning write (size 100) of single field" */
memcpy(my_struct.flex_array.payload, big_payload, sizeof(big_payload));
return 0;
}
```
Thanks,
Jesse Taube
>
> Thanks
> -Gustavo
>
> >
> > Thanks,
> > Jesse Taube
> >
> >>
> >>> +
> >>> /**
> >>> * __DEFINE_FLEX() - helper macro for DEFINE_FLEX() family.
> >>> * Enables caller macro to pass arbitrary trailing expressions
> >>> @@ -477,10 +530,7 @@ static __always_inline size_t __must_check
> >>> size_sub(size_t minuend, size_t subtr
> >>> #define __DEFINE_FLEX(type, name, member, count, trailer...)
> >>> \
> >>> _Static_assert(__builtin_constant_p(count),
> >>> \
> >>> "onstack flex array members require compile-time
> >>> const count"); \
> >>> - union {
> >>> \
> >>> - u8 bytes[struct_size_t(type, member, count)];
> >>> \
> >>> - type obj;
> >>> \
> >>> - } name##_u trailer;
> >>> \
> >>> + __DECLARE_SIZED_FLEX(type obj, member, count) name##_u trailer;
> >>> \
> >>> type *name = (type *)&name##_u
> >>
> >> -Kees
> >>
> >> --
> >> Kees Cook
> >>
> >
>