* [PATCH][next] bpf: Avoid thousands of -Wflex-array-members-not-at-end warnings
@ 2026-03-03 5:04 Gustavo A. R. Silva
2026-03-04 7:30 ` Kees Cook
0 siblings, 1 reply; 3+ messages in thread
From: Gustavo A. R. Silva @ 2026-03-03 5:04 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu,
Yonghong Song, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa
Cc: bpf, linux-kernel, Gustavo A. R. Silva, linux-hardening,
Kees Cook
-Wflex-array-member-not-at-end was introduced in GCC-14, and we are
getting ready to enable it, globally.
struct bpf_prog_array is a flexible structure, this is a structure that
contains a flexible-array member (struct bpf_prog_array_item items[];).
We create the new struct bpf_prog_array_hdr type, and use it to replace
the object type causing trouble in struct bpf_empty_prog_array, namely
struct bpf_prog_array hdr;
Also, once -fms-extensions is enabled, we can use transparent struct
members in struct bpf_prog_array.
Notice that the newly created type does not contain the flex-array
member `items`, which is the object causing the -Wfamnae warnings
in struct bpf_empty_prog_array.
With these changes, fix the following warnings:
7659 ./include/linux/bpf.h:2369:31: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
---
include/linux/bpf-cgroup.h | 2 +-
include/linux/bpf.h | 8 ++++++--
kernel/bpf/core.c | 6 +++---
3 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h
index 2f535331f926..e7d266600ac7 100644
--- a/include/linux/bpf-cgroup.h
+++ b/include/linux/bpf-cgroup.h
@@ -184,7 +184,7 @@ static inline bool cgroup_bpf_sock_enabled(struct sock *sk,
struct bpf_prog_array *array;
array = rcu_access_pointer(cgrp->bpf.effective[type]);
- return array != &bpf_empty_prog_array.hdr;
+ return (void *)array != (void *)&bpf_empty_prog_array.hdr;
}
/* Wrappers for __cgroup_bpf_run_filter_skb() guarded by cgroup_bpf_enabled. */
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 05b34a6355b0..488de065466e 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -2360,13 +2360,17 @@ struct bpf_prog_array_item {
};
};
-struct bpf_prog_array {
+struct bpf_prog_array_hdr {
struct rcu_head rcu;
+};
+
+struct bpf_prog_array {
+ struct bpf_prog_array_hdr;
struct bpf_prog_array_item items[];
};
struct bpf_empty_prog_array {
- struct bpf_prog_array hdr;
+ struct bpf_prog_array_hdr hdr;
struct bpf_prog *null_prog;
};
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 229c74f3d6ae..ac15ab8b7d3c 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -2598,14 +2598,14 @@ struct bpf_prog_array *bpf_prog_array_alloc(u32 prog_cnt, gfp_t flags)
if (prog_cnt)
p = kzalloc_flex(*p, items, prog_cnt + 1, flags);
else
- p = &bpf_empty_prog_array.hdr;
+ p = (void *)&bpf_empty_prog_array.hdr;
return p;
}
void bpf_prog_array_free(struct bpf_prog_array *progs)
{
- if (!progs || progs == &bpf_empty_prog_array.hdr)
+ if (!progs || (void *)progs == (void *)&bpf_empty_prog_array.hdr)
return;
kfree_rcu(progs, rcu);
}
@@ -2626,7 +2626,7 @@ static void __bpf_prog_array_free_sleepable_cb(struct rcu_head *rcu)
void bpf_prog_array_free_sleepable(struct bpf_prog_array *progs)
{
- if (!progs || progs == &bpf_empty_prog_array.hdr)
+ if (!progs || (void *)progs == (void *)&bpf_empty_prog_array.hdr)
return;
call_rcu_tasks_trace(&progs->rcu, __bpf_prog_array_free_sleepable_cb);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH][next] bpf: Avoid thousands of -Wflex-array-members-not-at-end warnings
2026-03-03 5:04 [PATCH][next] bpf: Avoid thousands of -Wflex-array-members-not-at-end warnings Gustavo A. R. Silva
@ 2026-03-04 7:30 ` Kees Cook
2026-03-24 21:50 ` Gustavo A. R. Silva
0 siblings, 1 reply; 3+ messages in thread
From: Kees Cook @ 2026-03-04 7:30 UTC (permalink / raw)
To: Gustavo A. R. Silva, Alexei Starovoitov, Daniel Borkmann,
John Fastabend, Andrii Nakryiko, Martin KaFai Lau,
Eduard Zingerman, Song Liu, Yonghong Song, KP Singh,
Stanislav Fomichev, Hao Luo, Jiri Olsa
Cc: bpf, linux-kernel, linux-hardening
On March 2, 2026 9:04:24 PM PST, "Gustavo A. R. Silva" <gustavoars@kernel.org> wrote:
>-Wflex-array-member-not-at-end was introduced in GCC-14, and we are
>getting ready to enable it, globally.
>
>struct bpf_prog_array is a flexible structure, this is a structure that
>contains a flexible-array member (struct bpf_prog_array_item items[];).
>
>We create the new struct bpf_prog_array_hdr type, and use it to replace
>the object type causing trouble in struct bpf_empty_prog_array, namely
>struct bpf_prog_array hdr;
>
>Also, once -fms-extensions is enabled, we can use transparent struct
Typo: "since" instead of "once".
>members in struct bpf_prog_array.
>
>Notice that the newly created type does not contain the flex-array
>member `items`, which is the object causing the -Wfamnae warnings
>in struct bpf_empty_prog_array.
>
>With these changes, fix the following warnings:
>
>7659 ./include/linux/bpf.h:2369:31: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
>
>Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
>---
> include/linux/bpf-cgroup.h | 2 +-
> include/linux/bpf.h | 8 ++++++--
> kernel/bpf/core.c | 6 +++---
> 3 files changed, 10 insertions(+), 6 deletions(-)
>
>diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h
>index 2f535331f926..e7d266600ac7 100644
>--- a/include/linux/bpf-cgroup.h
>+++ b/include/linux/bpf-cgroup.h
>@@ -184,7 +184,7 @@ static inline bool cgroup_bpf_sock_enabled(struct sock *sk,
> struct bpf_prog_array *array;
>
> array = rcu_access_pointer(cgrp->bpf.effective[type]);
>- return array != &bpf_empty_prog_array.hdr;
>+ return (void *)array != (void *)&bpf_empty_prog_array.hdr;
> }
>
> /* Wrappers for __cgroup_bpf_run_filter_skb() guarded by cgroup_bpf_enabled. */
>diff --git a/include/linux/bpf.h b/include/linux/bpf.h
>index 05b34a6355b0..488de065466e 100644
>--- a/include/linux/bpf.h
>+++ b/include/linux/bpf.h
>@@ -2360,13 +2360,17 @@ struct bpf_prog_array_item {
> };
> };
>
>-struct bpf_prog_array {
>+struct bpf_prog_array_hdr {
> struct rcu_head rcu;
>+};
>+
>+struct bpf_prog_array {
>+ struct bpf_prog_array_hdr;
> struct bpf_prog_array_item items[];
> };
>
> struct bpf_empty_prog_array {
>- struct bpf_prog_array hdr;
>+ struct bpf_prog_array_hdr hdr;
> struct bpf_prog *null_prog;
> };
AFAICT, this struct exists entirely to populate a single element of "items" in a global variable. (I only see "null_prog" used during the initializer.) None of this is needed; globals will be correctly sized with an array initializer of a FAM. Totally untested:
struct bpf_prog_array bpf_empty_prog_array = {
.items = { NULL, },
};
>
>diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
>index 229c74f3d6ae..ac15ab8b7d3c 100644
>--- a/kernel/bpf/core.c
>+++ b/kernel/bpf/core.c
>@@ -2598,14 +2598,14 @@ struct bpf_prog_array *bpf_prog_array_alloc(u32 prog_cnt, gfp_t flags)
> if (prog_cnt)
> p = kzalloc_flex(*p, items, prog_cnt + 1, flags);
> else
>- p = &bpf_empty_prog_array.hdr;
>+ p = (void *)&bpf_empty_prog_array.hdr;
Then there also shouldn't be any need for the casting (or the "hdr" addressing):
p = &bpf_empty_prog_array;
Etc
-Kees
>
> return p;
> }
>
> void bpf_prog_array_free(struct bpf_prog_array *progs)
> {
>- if (!progs || progs == &bpf_empty_prog_array.hdr)
>+ if (!progs || (void *)progs == (void *)&bpf_empty_prog_array.hdr)
> return;
> kfree_rcu(progs, rcu);
> }
>@@ -2626,7 +2626,7 @@ static void __bpf_prog_array_free_sleepable_cb(struct rcu_head *rcu)
>
> void bpf_prog_array_free_sleepable(struct bpf_prog_array *progs)
> {
>- if (!progs || progs == &bpf_empty_prog_array.hdr)
>+ if (!progs || (void *)progs == (void *)&bpf_empty_prog_array.hdr)
> return;
> call_rcu_tasks_trace(&progs->rcu, __bpf_prog_array_free_sleepable_cb);
> }
--
Kees Cook
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH][next] bpf: Avoid thousands of -Wflex-array-members-not-at-end warnings
2026-03-04 7:30 ` Kees Cook
@ 2026-03-24 21:50 ` Gustavo A. R. Silva
0 siblings, 0 replies; 3+ messages in thread
From: Gustavo A. R. Silva @ 2026-03-24 21:50 UTC (permalink / raw)
To: Kees Cook, Gustavo A. R. Silva, Alexei Starovoitov,
Daniel Borkmann, John Fastabend, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song,
KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa
Cc: bpf, linux-kernel, linux-hardening
On 3/4/26 01:30, Kees Cook wrote:
>
>
> On March 2, 2026 9:04:24 PM PST, "Gustavo A. R. Silva" <gustavoars@kernel.org> wrote:
>> -Wflex-array-member-not-at-end was introduced in GCC-14, and we are
>> getting ready to enable it, globally.
>>
>> struct bpf_prog_array is a flexible structure, this is a structure that
>> contains a flexible-array member (struct bpf_prog_array_item items[];).
>>
>> We create the new struct bpf_prog_array_hdr type, and use it to replace
>> the object type causing trouble in struct bpf_empty_prog_array, namely
>> struct bpf_prog_array hdr;
>>
>> Also, once -fms-extensions is enabled, we can use transparent struct
>
> Typo: "since" instead of "once".
Ah yes, thanks!
>
>> members in struct bpf_prog_array.
>>
>> Notice that the newly created type does not contain the flex-array
>> member `items`, which is the object causing the -Wfamnae warnings
>> in struct bpf_empty_prog_array.
>>
>> With these changes, fix the following warnings:
>>
>> 7659 ./include/linux/bpf.h:2369:31: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
>>
>> Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
>> ---
>> include/linux/bpf-cgroup.h | 2 +-
>> include/linux/bpf.h | 8 ++++++--
>> kernel/bpf/core.c | 6 +++---
>> 3 files changed, 10 insertions(+), 6 deletions(-)
>>
>> diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h
>> index 2f535331f926..e7d266600ac7 100644
>> --- a/include/linux/bpf-cgroup.h
>> +++ b/include/linux/bpf-cgroup.h
>> @@ -184,7 +184,7 @@ static inline bool cgroup_bpf_sock_enabled(struct sock *sk,
>> struct bpf_prog_array *array;
>>
>> array = rcu_access_pointer(cgrp->bpf.effective[type]);
>> - return array != &bpf_empty_prog_array.hdr;
>> + return (void *)array != (void *)&bpf_empty_prog_array.hdr;
>> }
>>
>> /* Wrappers for __cgroup_bpf_run_filter_skb() guarded by cgroup_bpf_enabled. */
>> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
>> index 05b34a6355b0..488de065466e 100644
>> --- a/include/linux/bpf.h
>> +++ b/include/linux/bpf.h
>> @@ -2360,13 +2360,17 @@ struct bpf_prog_array_item {
>> };
>> };
>>
>> -struct bpf_prog_array {
>> +struct bpf_prog_array_hdr {
>> struct rcu_head rcu;
>> +};
>> +
>> +struct bpf_prog_array {
>> + struct bpf_prog_array_hdr;
>> struct bpf_prog_array_item items[];
>> };
>>
>> struct bpf_empty_prog_array {
>> - struct bpf_prog_array hdr;
>> + struct bpf_prog_array_hdr hdr;
>> struct bpf_prog *null_prog;
>> };
>
> AFAICT, this struct exists entirely to populate a single element of "items" in a global variable. (I only see "null_prog" used during the initializer.) None of this is needed; globals will be correctly sized with an array initializer of a FAM. Totally untested:
>
> struct bpf_prog_array bpf_empty_prog_array = {
> .items = { NULL, },
> };
Okay, in this case the patch would look as follows:
diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h
index 2f535331f926..b2e79c2b41d5 100644
--- a/include/linux/bpf-cgroup.h
+++ b/include/linux/bpf-cgroup.h
@@ -184,7 +184,7 @@ static inline bool cgroup_bpf_sock_enabled(struct sock *sk,
struct bpf_prog_array *array;
array = rcu_access_pointer(cgrp->bpf.effective[type]);
- return array != &bpf_empty_prog_array.hdr;
+ return array != &bpf_empty_prog_array;
}
/* Wrappers for __cgroup_bpf_run_filter_skb() guarded by cgroup_bpf_enabled. */
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 05b34a6355b0..4f5b9e85a20c 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -2365,18 +2365,13 @@ struct bpf_prog_array {
struct bpf_prog_array_item items[];
};
-struct bpf_empty_prog_array {
- struct bpf_prog_array hdr;
- struct bpf_prog *null_prog;
-};
-
/* to avoid allocating empty bpf_prog_array for cgroups that
* don't have bpf program attached use one global 'bpf_empty_prog_array'
* It will not be modified the caller of bpf_prog_array_alloc()
* (since caller requested prog_cnt == 0)
* that pointer should be 'freed' by bpf_prog_array_free()
*/
-extern struct bpf_empty_prog_array bpf_empty_prog_array;
+extern struct bpf_prog_array bpf_empty_prog_array;
struct bpf_prog_array *bpf_prog_array_alloc(u32 prog_cnt, gfp_t flags);
void bpf_prog_array_free(struct bpf_prog_array *progs);
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 67eb12b637a5..ca39d2e690b9 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -2613,8 +2613,10 @@ static struct bpf_prog_dummy {
},
};
-struct bpf_empty_prog_array bpf_empty_prog_array = {
- .null_prog = NULL,
+struct bpf_prog_array bpf_empty_prog_array = {
+ .items = {
+ { .prog = NULL },
+ },
};
EXPORT_SYMBOL(bpf_empty_prog_array);
@@ -2625,14 +2627,14 @@ struct bpf_prog_array *bpf_prog_array_alloc(u32 prog_cnt, gfp_t flags)
if (prog_cnt)
p = kzalloc_flex(*p, items, prog_cnt + 1, flags);
else
- p = &bpf_empty_prog_array.hdr;
+ p = &bpf_empty_prog_array;
return p;
}
void bpf_prog_array_free(struct bpf_prog_array *progs)
{
- if (!progs || progs == &bpf_empty_prog_array.hdr)
+ if (!progs || progs == &bpf_empty_prog_array)
return;
kfree_rcu(progs, rcu);
}
@@ -2653,7 +2655,7 @@ static void __bpf_prog_array_free_sleepable_cb(struct rcu_head *rcu)
void bpf_prog_array_free_sleepable(struct bpf_prog_array *progs)
{
- if (!progs || progs == &bpf_empty_prog_array.hdr)
+ if (!progs || progs == &bpf_empty_prog_array)
return;
call_rcu_tasks_trace(&progs->rcu, __bpf_prog_array_free_sleepable_cb);
}
Could maintainers give us feedback or comment on this, please? :)
Thanks!
-Gustavo
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-03-24 21:51 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-03 5:04 [PATCH][next] bpf: Avoid thousands of -Wflex-array-members-not-at-end warnings Gustavo A. R. Silva
2026-03-04 7:30 ` Kees Cook
2026-03-24 21:50 ` Gustavo A. R. Silva
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox