* [LTP] [PATCH] syscalls/bpf: zero-initialize bpf_attr including padding bits
@ 2025-02-06 12:56 Jan Stancek
2025-02-06 13:36 ` Cyril Hrubis
2025-02-06 14:08 ` Cyril Hrubis
0 siblings, 2 replies; 8+ messages in thread
From: Jan Stancek @ 2025-02-06 12:56 UTC (permalink / raw)
To: ltp
gcc 15 stopped zero-initializing padding bits:
https://gcc.gnu.org/gcc-15/changes.html
However kernel bpf syscall checks that all unused fields for a command
are set to zero in CHECK_ATTR() macro, which causes tests to fail with
EINVAL.
Signed-off-by: Jan Stancek <jstancek@redhat.com>
---
testcases/kernel/syscalls/bpf/bpf_common.c | 32 ++++++++++++----------
1 file changed, 18 insertions(+), 14 deletions(-)
diff --git a/testcases/kernel/syscalls/bpf/bpf_common.c b/testcases/kernel/syscalls/bpf/bpf_common.c
index 95b5bc12eaa4..d765c4e32936 100644
--- a/testcases/kernel/syscalls/bpf/bpf_common.c
+++ b/testcases/kernel/syscalls/bpf/bpf_common.c
@@ -49,13 +49,14 @@ int bpf_map_create(union bpf_attr *const attr)
int bpf_map_array_create(const uint32_t max_entries)
{
- union bpf_attr map_attr = {
- .map_type = BPF_MAP_TYPE_ARRAY,
- .key_size = 4,
- .value_size = 8,
- .max_entries = max_entries,
- .map_flags = 0
- };
+ /* zero-initialize entire struct including padding bits */
+ union bpf_attr map_attr = {};
+
+ map_attr.map_type = BPF_MAP_TYPE_ARRAY;
+ map_attr.key_size = 4;
+ map_attr.value_size = 8;
+ map_attr.max_entries = max_entries;
+ map_attr.map_flags = 0;
return bpf_map_create(&map_attr);
}
@@ -64,13 +65,16 @@ void bpf_map_array_get(const int map_fd,
const uint32_t *const array_indx,
uint64_t *const array_val)
{
- union bpf_attr elem_attr = {
- .map_fd = map_fd,
- .key = ptr_to_u64(array_indx),
- .value = ptr_to_u64(array_val),
- .flags = 0
- };
- const int ret = bpf(BPF_MAP_LOOKUP_ELEM, &elem_attr, sizeof(elem_attr));
+ /* zero-initialize entire struct including padding bits */
+ union bpf_attr elem_attr = {};
+ int ret;
+
+ elem_attr.map_fd = map_fd;
+ elem_attr.key = ptr_to_u64(array_indx);
+ elem_attr.value = ptr_to_u64(array_val);
+ elem_attr.flags = 0;
+
+ ret = bpf(BPF_MAP_LOOKUP_ELEM, &elem_attr, sizeof(elem_attr));
if (ret) {
tst_brk(TBROK | TTERRNO,
--
2.43.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [LTP] [PATCH] syscalls/bpf: zero-initialize bpf_attr including padding bits
2025-02-06 12:56 [LTP] [PATCH] syscalls/bpf: zero-initialize bpf_attr including padding bits Jan Stancek
@ 2025-02-06 13:36 ` Cyril Hrubis
2025-02-06 14:08 ` Cyril Hrubis
1 sibling, 0 replies; 8+ messages in thread
From: Cyril Hrubis @ 2025-02-06 13:36 UTC (permalink / raw)
To: Jan Stancek; +Cc: ltp
Hi!
> gcc 15 stopped zero-initializing padding bits:
> https://gcc.gnu.org/gcc-15/changes.html
I would even call this a bug even if it's allowed by the C standard.
> However kernel bpf syscall checks that all unused fields for a command
> are set to zero in CHECK_ATTR() macro, which causes tests to fail with
> EINVAL.
>
> Signed-off-by: Jan Stancek <jstancek@redhat.com>
> ---
> testcases/kernel/syscalls/bpf/bpf_common.c | 32 ++++++++++++----------
> 1 file changed, 18 insertions(+), 14 deletions(-)
>
> diff --git a/testcases/kernel/syscalls/bpf/bpf_common.c b/testcases/kernel/syscalls/bpf/bpf_common.c
> index 95b5bc12eaa4..d765c4e32936 100644
> --- a/testcases/kernel/syscalls/bpf/bpf_common.c
> +++ b/testcases/kernel/syscalls/bpf/bpf_common.c
> @@ -49,13 +49,14 @@ int bpf_map_create(union bpf_attr *const attr)
>
> int bpf_map_array_create(const uint32_t max_entries)
> {
> - union bpf_attr map_attr = {
> - .map_type = BPF_MAP_TYPE_ARRAY,
> - .key_size = 4,
> - .value_size = 8,
> - .max_entries = max_entries,
> - .map_flags = 0
> - };
> + /* zero-initialize entire struct including padding bits */
> + union bpf_attr map_attr = {};
> +
> + map_attr.map_type = BPF_MAP_TYPE_ARRAY;
> + map_attr.key_size = 4;
> + map_attr.value_size = 8;
> + map_attr.max_entries = max_entries;
> + map_attr.map_flags = 0;
So struct foo bar = {.bar = foo}; does not work,
but struct foo bar = {}: bar.bar = foo; does? That is insane...
> return bpf_map_create(&map_attr);
> }
> @@ -64,13 +65,16 @@ void bpf_map_array_get(const int map_fd,
> const uint32_t *const array_indx,
> uint64_t *const array_val)
> {
> - union bpf_attr elem_attr = {
> - .map_fd = map_fd,
> - .key = ptr_to_u64(array_indx),
> - .value = ptr_to_u64(array_val),
> - .flags = 0
> - };
> - const int ret = bpf(BPF_MAP_LOOKUP_ELEM, &elem_attr, sizeof(elem_attr));
> + /* zero-initialize entire struct including padding bits */
> + union bpf_attr elem_attr = {};
> + int ret;
> +
> + elem_attr.map_fd = map_fd;
> + elem_attr.key = ptr_to_u64(array_indx);
> + elem_attr.value = ptr_to_u64(array_val);
> + elem_attr.flags = 0;
> +
> + ret = bpf(BPF_MAP_LOOKUP_ELEM, &elem_attr, sizeof(elem_attr));
>
> if (ret) {
> tst_brk(TBROK | TTERRNO,
> --
> 2.43.0
>
>
> --
> Mailing list info: https://lists.linux.it/listinfo/ltp
--
Cyril Hrubis
chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [LTP] [PATCH] syscalls/bpf: zero-initialize bpf_attr including padding bits
2025-02-06 12:56 [LTP] [PATCH] syscalls/bpf: zero-initialize bpf_attr including padding bits Jan Stancek
2025-02-06 13:36 ` Cyril Hrubis
@ 2025-02-06 14:08 ` Cyril Hrubis
2025-02-06 14:34 ` Jan Stancek
2025-02-06 21:23 ` [LTP] [PATCH v2] " Jan Stancek
1 sibling, 2 replies; 8+ messages in thread
From: Cyril Hrubis @ 2025-02-06 14:08 UTC (permalink / raw)
To: Jan Stancek; +Cc: ltp
Hi!
> However kernel bpf syscall checks that all unused fields for a command
> are set to zero in CHECK_ATTR() macro, which causes tests to fail with
> EINVAL.
>
> Signed-off-by: Jan Stancek <jstancek@redhat.com>
> ---
> testcases/kernel/syscalls/bpf/bpf_common.c | 32 ++++++++++++----------
> 1 file changed, 18 insertions(+), 14 deletions(-)
>
> diff --git a/testcases/kernel/syscalls/bpf/bpf_common.c b/testcases/kernel/syscalls/bpf/bpf_common.c
> index 95b5bc12eaa4..d765c4e32936 100644
> --- a/testcases/kernel/syscalls/bpf/bpf_common.c
> +++ b/testcases/kernel/syscalls/bpf/bpf_common.c
> @@ -49,13 +49,14 @@ int bpf_map_create(union bpf_attr *const attr)
>
> int bpf_map_array_create(const uint32_t max_entries)
> {
> - union bpf_attr map_attr = {
> - .map_type = BPF_MAP_TYPE_ARRAY,
> - .key_size = 4,
> - .value_size = 8,
> - .max_entries = max_entries,
> - .map_flags = 0
> - };
> + /* zero-initialize entire struct including padding bits */
> + union bpf_attr map_attr = {};
> +
> + map_attr.map_type = BPF_MAP_TYPE_ARRAY;
> + map_attr.key_size = 4;
> + map_attr.value_size = 8;
> + map_attr.max_entries = max_entries;
> + map_attr.map_flags = 0;
I had a closer look here, the map_attr is an union with anonymous
structures and I suppose that the problem here is that the padding after
the union is no longer cleared and that there have been some new fields
added, at least compared to the lapi fallback structures we have and we
possibly pass random mess in flags.
Maybe slightly better version would be:
diff --git a/testcases/kernel/syscalls/bpf/bpf_common.c b/testcases/kernel/syscalls/bpf/bpf_common.c
index 95b5bc12e..a8289e106 100644
--- a/testcases/kernel/syscalls/bpf/bpf_common.c
+++ b/testcases/kernel/syscalls/bpf/bpf_common.c
@@ -49,7 +49,9 @@ int bpf_map_create(union bpf_attr *const attr)
int bpf_map_array_create(const uint32_t max_entries)
{
- union bpf_attr map_attr = {
+ union bpf_attr map_attr = {};
+
+ map_attr = (union bpf_attr) {
.map_type = BPF_MAP_TYPE_ARRAY,
.key_size = 4,
.value_size = 8,
--
Cyril Hrubis
chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [LTP] [PATCH] syscalls/bpf: zero-initialize bpf_attr including padding bits
2025-02-06 14:08 ` Cyril Hrubis
@ 2025-02-06 14:34 ` Jan Stancek
2025-02-06 15:04 ` Cyril Hrubis
2025-02-06 21:23 ` [LTP] [PATCH v2] " Jan Stancek
1 sibling, 1 reply; 8+ messages in thread
From: Jan Stancek @ 2025-02-06 14:34 UTC (permalink / raw)
To: Cyril Hrubis; +Cc: ltp
On Thu, Feb 6, 2025 at 3:08 PM Cyril Hrubis <chrubis@suse.cz> wrote:
>
> Hi!
> > However kernel bpf syscall checks that all unused fields for a command
> > are set to zero in CHECK_ATTR() macro, which causes tests to fail with
> > EINVAL.
> >
> > Signed-off-by: Jan Stancek <jstancek@redhat.com>
> > ---
> > testcases/kernel/syscalls/bpf/bpf_common.c | 32 ++++++++++++----------
> > 1 file changed, 18 insertions(+), 14 deletions(-)
> >
> > diff --git a/testcases/kernel/syscalls/bpf/bpf_common.c b/testcases/kernel/syscalls/bpf/bpf_common.c
> > index 95b5bc12eaa4..d765c4e32936 100644
> > --- a/testcases/kernel/syscalls/bpf/bpf_common.c
> > +++ b/testcases/kernel/syscalls/bpf/bpf_common.c
> > @@ -49,13 +49,14 @@ int bpf_map_create(union bpf_attr *const attr)
> >
> > int bpf_map_array_create(const uint32_t max_entries)
> > {
> > - union bpf_attr map_attr = {
> > - .map_type = BPF_MAP_TYPE_ARRAY,
> > - .key_size = 4,
> > - .value_size = 8,
> > - .max_entries = max_entries,
> > - .map_flags = 0
> > - };
> > + /* zero-initialize entire struct including padding bits */
> > + union bpf_attr map_attr = {};
> > +
> > + map_attr.map_type = BPF_MAP_TYPE_ARRAY;
> > + map_attr.key_size = 4;
> > + map_attr.value_size = 8;
> > + map_attr.max_entries = max_entries;
> > + map_attr.map_flags = 0;
>
> I had a closer look here, the map_attr is an union with anonymous
> structures and I suppose that the problem here is that the padding after
> the union is no longer cleared and that there have been some new fields
> added, at least compared to the lapi fallback structures we have and we
> possibly pass random mess in flags.
It's not just padding, some fields (from other structs) are also not
initialized:
void bpf_map_array_get(const int map_fd,
const uint32_t *const array_indx,
uint64_t *const array_val)
{
union bpf_attr elem_attr = {
.map_fd = map_fd,
.key = ptr_to_u64(array_indx),
.value = ptr_to_u64(array_val),
.flags = 0
};
printf("should be zero? %u\n", elem_attr.func_info_cnt);
and I get:
should be zero? 4202093
func_info_cnt is at offset 88, which is far away from ones we
initialized explicitly:
struct {
uint32_t map_fd; /* 0 4 */
/* XXX 4 bytes hole, try to pack */
uint64_t key
__attribute__((__aligned__(8))); /* 8 8 */
union {
uint64_t value
__attribute__((__aligned__(8))); /* 16 8 */
uint64_t next_key
__attribute__((__aligned__(8))); /* 16 8 */
} __attribute__((__aligned__(8))); /* 16 8 */
uint64_t flags; /* 24 8 */
} __attribute__((__aligned__(8)))
__attribute__((__aligned__(8))); /* 0 32 */
>
> Maybe slightly better version would be:
>
> diff --git a/testcases/kernel/syscalls/bpf/bpf_common.c b/testcases/kernel/syscalls/bpf/bpf_common.c
> index 95b5bc12e..a8289e106 100644
> --- a/testcases/kernel/syscalls/bpf/bpf_common.c
> +++ b/testcases/kernel/syscalls/bpf/bpf_common.c
> @@ -49,7 +49,9 @@ int bpf_map_create(union bpf_attr *const attr)
>
> int bpf_map_array_create(const uint32_t max_entries)
> {
> - union bpf_attr map_attr = {
> + union bpf_attr map_attr = {};
> +
> + map_attr = (union bpf_attr) {
> .map_type = BPF_MAP_TYPE_ARRAY,
> .key_size = 4,
> .value_size = 8,
>
>
> --
> Cyril Hrubis
> chrubis@suse.cz
>
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [LTP] [PATCH] syscalls/bpf: zero-initialize bpf_attr including padding bits
2025-02-06 14:34 ` Jan Stancek
@ 2025-02-06 15:04 ` Cyril Hrubis
0 siblings, 0 replies; 8+ messages in thread
From: Cyril Hrubis @ 2025-02-06 15:04 UTC (permalink / raw)
To: Jan Stancek; +Cc: ltp
Hi!
> > I had a closer look here, the map_attr is an union with anonymous
> > structures and I suppose that the problem here is that the padding after
> > the union is no longer cleared and that there have been some new fields
> > added, at least compared to the lapi fallback structures we have and we
> > possibly pass random mess in flags.
>
> It's not just padding, some fields (from other structs) are also not
> initialized:
>
> void bpf_map_array_get(const int map_fd,
> const uint32_t *const array_indx,
> uint64_t *const array_val)
> {
> union bpf_attr elem_attr = {
> .map_fd = map_fd,
> .key = ptr_to_u64(array_indx),
> .value = ptr_to_u64(array_val),
> .flags = 0
> };
>
> printf("should be zero? %u\n", elem_attr.func_info_cnt);
>
> and I get:
> should be zero? 4202093
That's what I meant, but phrased it wrongly. Padding after the shorter
union fields, which are anonymous structures. That means that quite a
lot of the fields may end up non-zeroed in case that we initialize
a structure that is on the shorter side. I would say that in this case
the optimalization is very evil one, because it looks like these members
should have been zeroed at first.
--
Cyril Hrubis
chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 8+ messages in thread
* [LTP] [PATCH v2] syscalls/bpf: zero-initialize bpf_attr including padding bits
2025-02-06 14:08 ` Cyril Hrubis
2025-02-06 14:34 ` Jan Stancek
@ 2025-02-06 21:23 ` Jan Stancek
2025-02-07 8:35 ` Cyril Hrubis
1 sibling, 1 reply; 8+ messages in thread
From: Jan Stancek @ 2025-02-06 21:23 UTC (permalink / raw)
To: ltp
gcc 15 stopped zero-initializing padding bits:
https://gcc.gnu.org/gcc-15/changes.html
However kernel bpf syscall checks that all unused fields for a command
are set to zero in CHECK_ATTR() macro, which causes tests to fail with
EINVAL.
Signed-off-by: Jan Stancek <jstancek@redhat.com>
---
v2 changes:
- Use slightly better version suggested by Cyril
testcases/kernel/syscalls/bpf/bpf_common.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/testcases/kernel/syscalls/bpf/bpf_common.c b/testcases/kernel/syscalls/bpf/bpf_common.c
index 95b5bc12eaa4..9148b0437279 100644
--- a/testcases/kernel/syscalls/bpf/bpf_common.c
+++ b/testcases/kernel/syscalls/bpf/bpf_common.c
@@ -49,7 +49,10 @@ int bpf_map_create(union bpf_attr *const attr)
int bpf_map_array_create(const uint32_t max_entries)
{
- union bpf_attr map_attr = {
+ /* zero-initialize entire struct including padding bits */
+ union bpf_attr map_attr = {};
+
+ map_attr = (union bpf_attr) {
.map_type = BPF_MAP_TYPE_ARRAY,
.key_size = 4,
.value_size = 8,
@@ -64,13 +67,18 @@ void bpf_map_array_get(const int map_fd,
const uint32_t *const array_indx,
uint64_t *const array_val)
{
- union bpf_attr elem_attr = {
+ /* zero-initialize entire struct including padding bits */
+ union bpf_attr elem_attr = {};
+ int ret;
+
+ elem_attr = (union bpf_attr) {
.map_fd = map_fd,
.key = ptr_to_u64(array_indx),
.value = ptr_to_u64(array_val),
.flags = 0
};
- const int ret = bpf(BPF_MAP_LOOKUP_ELEM, &elem_attr, sizeof(elem_attr));
+
+ ret = bpf(BPF_MAP_LOOKUP_ELEM, &elem_attr, sizeof(elem_attr));
if (ret) {
tst_brk(TBROK | TTERRNO,
--
2.43.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [LTP] [PATCH v2] syscalls/bpf: zero-initialize bpf_attr including padding bits
2025-02-06 21:23 ` [LTP] [PATCH v2] " Jan Stancek
@ 2025-02-07 8:35 ` Cyril Hrubis
2025-02-07 9:47 ` Jan Stancek
0 siblings, 1 reply; 8+ messages in thread
From: Cyril Hrubis @ 2025-02-07 8:35 UTC (permalink / raw)
To: Jan Stancek; +Cc: ltp
Hi!
Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
--
Cyril Hrubis
chrubis@suse.cz
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [LTP] [PATCH v2] syscalls/bpf: zero-initialize bpf_attr including padding bits
2025-02-07 8:35 ` Cyril Hrubis
@ 2025-02-07 9:47 ` Jan Stancek
0 siblings, 0 replies; 8+ messages in thread
From: Jan Stancek @ 2025-02-07 9:47 UTC (permalink / raw)
To: Cyril Hrubis; +Cc: ltp
On Fri, Feb 7, 2025 at 9:35 AM Cyril Hrubis <chrubis@suse.cz> wrote:
>
> Hi!
> Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
Pushed.
Thanks,
Jan
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2025-02-07 9:48 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-06 12:56 [LTP] [PATCH] syscalls/bpf: zero-initialize bpf_attr including padding bits Jan Stancek
2025-02-06 13:36 ` Cyril Hrubis
2025-02-06 14:08 ` Cyril Hrubis
2025-02-06 14:34 ` Jan Stancek
2025-02-06 15:04 ` Cyril Hrubis
2025-02-06 21:23 ` [LTP] [PATCH v2] " Jan Stancek
2025-02-07 8:35 ` Cyril Hrubis
2025-02-07 9:47 ` Jan Stancek
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox