On 8/2/23 00:31, Kees Cook wrote:
[...]
Initially I was struggling to make __counted_by work, but it seems we can
use an initializer for that member, as long as we don't touch the flexible
array member in the initializer. So we just need to add the counted-by
member to the macro, and use a union to do the initialization. And if
we take the address of the union (and not the struct within it), the
compiler will see the correct object size with __builtin_object_size:
#define DEFINE_FLEX(type, name, flex, counter, count) \
union { \
u8 bytes[struct_size_t(type, flex, count)]; \
type obj; \
} name##_u __aligned(_Alignof(type)) = { .obj.counter = count }; \
/* take address of whole union to get the correct __builtin_object_size */ \
type *name = (type *)&name##_u
i.e. __builtin_object_size(name, 1) (as used by FORTIFY_SOURCE, etc)
works correctly here, but breaks (sees a zero-sized flex array member)
if this macro ends with:
type *name = &name##_u.obj
__builtin_object_size(name, 0) works fine for both versions (with and
without .obj at the end)
however it does not work for builds without -O2 switch, so
struct_size_t() is rather a way to go :/
-Kees
[1] https://git.kernel.org/linus/dd06e72e68bcb4070ef211be100d2896e236c8fb