* [PATCH] bpf: Annotate struct bpf_cand_cache with __counted_by()
@ 2024-08-13 15:17 Thorsten Blum
2024-08-13 16:28 ` Alexei Starovoitov
0 siblings, 1 reply; 7+ messages in thread
From: Thorsten Blum @ 2024-08-13 15:17 UTC (permalink / raw)
To: martin.lau, ast, daniel, andrii, eddyz87, song, yonghong.song,
john.fastabend, kpsingh, sdf, haoluo, jolsa, kees, gustavoars
Cc: bpf, linux-kernel, linux-hardening, Thorsten Blum
Add the __counted_by compiler attribute to the flexible array member
cands to improve access bounds-checking via CONFIG_UBSAN_BOUNDS and
CONFIG_FORTIFY_SOURCE.
Increment cnt before adding a new struct to the cands array.
Signed-off-by: Thorsten Blum <thorsten.blum@toblux.com>
---
kernel/bpf/btf.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 520f49f422fe..42bc70a56fcd 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -7240,7 +7240,7 @@ struct bpf_cand_cache {
struct {
const struct btf *btf;
u32 id;
- } cands[];
+ } cands[] __counted_by(cnt);
};
static DEFINE_MUTEX(cand_cache_mutex);
@@ -8784,9 +8784,9 @@ bpf_core_add_cands(struct bpf_cand_cache *cands, const struct btf *targ_btf,
memcpy(new_cands, cands, sizeof_cands(cands->cnt));
bpf_free_cands(cands);
cands = new_cands;
- cands->cands[cands->cnt].btf = targ_btf;
- cands->cands[cands->cnt].id = i;
cands->cnt++;
+ cands->cands[cands->cnt - 1].btf = targ_btf;
+ cands->cands[cands->cnt - 1].id = i;
}
return cands;
}
--
2.46.0
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH] bpf: Annotate struct bpf_cand_cache with __counted_by()
2024-08-13 15:17 [PATCH] bpf: Annotate struct bpf_cand_cache with __counted_by() Thorsten Blum
@ 2024-08-13 16:28 ` Alexei Starovoitov
2024-08-13 17:59 ` Thorsten Blum
0 siblings, 1 reply; 7+ messages in thread
From: Alexei Starovoitov @ 2024-08-13 16:28 UTC (permalink / raw)
To: Thorsten Blum
Cc: Martin KaFai Lau, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eddy Z, Song Liu, Yonghong Song, John Fastabend,
KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Kees Cook,
Gustavo A. R. Silva, bpf, LKML, linux-hardening
On Tue, Aug 13, 2024 at 8:19 AM Thorsten Blum <thorsten.blum@toblux.com> wrote:
>
> Add the __counted_by compiler attribute to the flexible array member
> cands to improve access bounds-checking via CONFIG_UBSAN_BOUNDS and
> CONFIG_FORTIFY_SOURCE.
>
> Increment cnt before adding a new struct to the cands array.
why? What happens otherwise?
>
> Signed-off-by: Thorsten Blum <thorsten.blum@toblux.com>
> ---
> kernel/bpf/btf.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
> index 520f49f422fe..42bc70a56fcd 100644
> --- a/kernel/bpf/btf.c
> +++ b/kernel/bpf/btf.c
> @@ -7240,7 +7240,7 @@ struct bpf_cand_cache {
> struct {
> const struct btf *btf;
> u32 id;
> - } cands[];
> + } cands[] __counted_by(cnt);
> };
>
> static DEFINE_MUTEX(cand_cache_mutex);
> @@ -8784,9 +8784,9 @@ bpf_core_add_cands(struct bpf_cand_cache *cands, const struct btf *targ_btf,
> memcpy(new_cands, cands, sizeof_cands(cands->cnt));
> bpf_free_cands(cands);
> cands = new_cands;
> - cands->cands[cands->cnt].btf = targ_btf;
> - cands->cands[cands->cnt].id = i;
> cands->cnt++;
> + cands->cands[cands->cnt - 1].btf = targ_btf;
> + cands->cands[cands->cnt - 1].id = i;
> }
> return cands;
> }
> --
> 2.46.0
>
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH] bpf: Annotate struct bpf_cand_cache with __counted_by()
2024-08-13 16:28 ` Alexei Starovoitov
@ 2024-08-13 17:59 ` Thorsten Blum
2024-08-13 18:57 ` Alexei Starovoitov
0 siblings, 1 reply; 7+ messages in thread
From: Thorsten Blum @ 2024-08-13 17:59 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Martin KaFai Lau, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eddy Z, Song Liu, Yonghong Song, John Fastabend,
KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Kees Cook,
Gustavo A. R. Silva, bpf, LKML, linux-hardening
On 13. Aug 2024, at 18:28, Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
> On Tue, Aug 13, 2024 at 8:19 AM Thorsten Blum <thorsten.blum@toblux.com> wrote:
>>
>> Add the __counted_by compiler attribute to the flexible array member
>> cands to improve access bounds-checking via CONFIG_UBSAN_BOUNDS and
>> CONFIG_FORTIFY_SOURCE.
>>
>> Increment cnt before adding a new struct to the cands array.
>
> why? What happens otherwise?
If you try to access cands->cands[cands->cnt] without incrementing
cands->cnt first, you're essentially accessing the array out of bounds
which will fail during runtime.
You can read more about it at [1] and [2].
> Signed-off-by: Thorsten Blum <thorsten.blum@toblux.com>
>> ---
>> kernel/bpf/btf.c | 6 +++---
>> 1 file changed, 3 insertions(+), 3 deletions(-)
>>
>> diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
>> index 520f49f422fe..42bc70a56fcd 100644
>> --- a/kernel/bpf/btf.c
>> +++ b/kernel/bpf/btf.c
>> @@ -7240,7 +7240,7 @@ struct bpf_cand_cache {
>> struct {
>> const struct btf *btf;
>> u32 id;
>> - } cands[];
>> + } cands[] __counted_by(cnt);
>> };
>>
>> static DEFINE_MUTEX(cand_cache_mutex);
>> @@ -8784,9 +8784,9 @@ bpf_core_add_cands(struct bpf_cand_cache *cands, const struct btf *targ_btf,
>> memcpy(new_cands, cands, sizeof_cands(cands->cnt));
>> bpf_free_cands(cands);
>> cands = new_cands;
>> - cands->cands[cands->cnt].btf = targ_btf;
>> - cands->cands[cands->cnt].id = i;
>> cands->cnt++;
>> + cands->cands[cands->cnt - 1].btf = targ_btf;
>> + cands->cands[cands->cnt - 1].id = i;
>> }
>> return cands;
>> }
>> --
>> 2.46.0
>>
[1] https://opensource.googleblog.com/2024/07/bounds-checking-flexible-array-members.html
[2] https://embeddedor.com/blog/2024/06/18/how-to-use-the-new-counted_by-attribute-in-c-and-linux/
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH] bpf: Annotate struct bpf_cand_cache with __counted_by()
2024-08-13 17:59 ` Thorsten Blum
@ 2024-08-13 18:57 ` Alexei Starovoitov
2024-08-13 20:12 ` Eduard Zingerman
2024-08-13 20:51 ` Thorsten Blum
0 siblings, 2 replies; 7+ messages in thread
From: Alexei Starovoitov @ 2024-08-13 18:57 UTC (permalink / raw)
To: Thorsten Blum
Cc: Martin KaFai Lau, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eddy Z, Song Liu, Yonghong Song, John Fastabend,
KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Kees Cook,
Gustavo A. R. Silva, bpf, LKML, linux-hardening
On Tue, Aug 13, 2024 at 10:59 AM Thorsten Blum <thorsten.blum@toblux.com> wrote:
>
> On 13. Aug 2024, at 18:28, Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
> > On Tue, Aug 13, 2024 at 8:19 AM Thorsten Blum <thorsten.blum@toblux.com> wrote:
> >>
> >> Add the __counted_by compiler attribute to the flexible array member
> >> cands to improve access bounds-checking via CONFIG_UBSAN_BOUNDS and
> >> CONFIG_FORTIFY_SOURCE.
> >>
> >> Increment cnt before adding a new struct to the cands array.
> >
> > why? What happens otherwise?
>
> If you try to access cands->cands[cands->cnt] without incrementing
> cands->cnt first, you're essentially accessing the array out of bounds
> which will fail during runtime.
What kind of error/warn do you see ?
Is it runtime or compile time?
Is this the only place?
what about:
new_cands = kmemdup(cands, sizeof_cands(cands->cnt), GFP_KERNEL);
cnt field gets copied with other fields.
Can compiler/runtime catch that?
> You can read more about it at [1] and [2].
>
> > Signed-off-by: Thorsten Blum <thorsten.blum@toblux.com>
> >> ---
> >> kernel/bpf/btf.c | 6 +++---
> >> 1 file changed, 3 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
> >> index 520f49f422fe..42bc70a56fcd 100644
> >> --- a/kernel/bpf/btf.c
> >> +++ b/kernel/bpf/btf.c
> >> @@ -7240,7 +7240,7 @@ struct bpf_cand_cache {
> >> struct {
> >> const struct btf *btf;
> >> u32 id;
> >> - } cands[];
> >> + } cands[] __counted_by(cnt);
> >> };
> >>
> >> static DEFINE_MUTEX(cand_cache_mutex);
> >> @@ -8784,9 +8784,9 @@ bpf_core_add_cands(struct bpf_cand_cache *cands, const struct btf *targ_btf,
> >> memcpy(new_cands, cands, sizeof_cands(cands->cnt));
> >> bpf_free_cands(cands);
> >> cands = new_cands;
> >> - cands->cands[cands->cnt].btf = targ_btf;
> >> - cands->cands[cands->cnt].id = i;
> >> cands->cnt++;
> >> + cands->cands[cands->cnt - 1].btf = targ_btf;
> >> + cands->cands[cands->cnt - 1].id = i;
> >> }
> >> return cands;
> >> }
> >> --
> >> 2.46.0
> >>
>
> [1] https://opensource.googleblog.com/2024/07/bounds-checking-flexible-array-members.html
> [2] https://embeddedor.com/blog/2024/06/18/how-to-use-the-new-counted_by-attribute-in-c-and-linux/
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH] bpf: Annotate struct bpf_cand_cache with __counted_by()
2024-08-13 18:57 ` Alexei Starovoitov
@ 2024-08-13 20:12 ` Eduard Zingerman
2024-08-13 20:51 ` Thorsten Blum
1 sibling, 0 replies; 7+ messages in thread
From: Eduard Zingerman @ 2024-08-13 20:12 UTC (permalink / raw)
To: Alexei Starovoitov, Thorsten Blum
Cc: Martin KaFai Lau, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Song Liu, Yonghong Song, John Fastabend,
KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Kees Cook,
Gustavo A. R. Silva, bpf, LKML, linux-hardening
On Tue, 2024-08-13 at 11:57 -0700, Alexei Starovoitov wrote:
> On Tue, Aug 13, 2024 at 10:59 AM Thorsten Blum <thorsten.blum@toblux.com> wrote:
> >
> > On 13. Aug 2024, at 18:28, Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
> > > On Tue, Aug 13, 2024 at 8:19 AM Thorsten Blum <thorsten.blum@toblux.com> wrote:
> > > >
> > > > Add the __counted_by compiler attribute to the flexible array member
> > > > cands to improve access bounds-checking via CONFIG_UBSAN_BOUNDS and
> > > > CONFIG_FORTIFY_SOURCE.
> > > >
> > > > Increment cnt before adding a new struct to the cands array.
> > >
> > > why? What happens otherwise?
> >
> > If you try to access cands->cands[cands->cnt] without incrementing
> > cands->cnt first, you're essentially accessing the array out of bounds
> > which will fail during runtime.
>
> What kind of error/warn do you see ?
> Is it runtime or compile time?
>
> Is this the only place?
> what about:
> new_cands = kmemdup(cands, sizeof_cands(cands->cnt), GFP_KERNEL);
>
> cnt field gets copied with other fields.
> Can compiler/runtime catch that?
I think that generated check is mechanical, sanitizer wraps access to
array with size check using the value of associated counter, e.g:
12:52:20 tmp$ clang -fsanitize=undefined ./test.c
12:52:53 tmp$ ./a.out
test.c:11:3: runtime error: index 0 out of bounds for type 'int[]'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior test.c:11:3
12:52:55 tmp$ cat test.c
#include <alloca.h>
struct arr {
int cnt;
int items[] __attribute__((__counted_by__(cnt)));
};
int main(int argc, char **argv) {
struct arr *arr = alloca(sizeof(struct arr) + sizeof(int));
arr->cnt = 0;
arr->items[arr->cnt] = 42;
arr->cnt++;
asm volatile (""::"r"(arr));
return 0;
}
12:53:07 tmp$ clang -fsanitize=undefined ./test.c
12:53:10 tmp$ ./a.out
test.c:11:3: runtime error: index 0 out of bounds for type 'int[]'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior test.c:11:3
12:53:13 tmp$ cat test.c
#include <alloca.h>
struct arr {
int cnt;
int items[] __attribute__((__counted_by__(cnt)));
};
int main(int argc, char **argv) {
struct arr *arr = alloca(sizeof(struct arr) + sizeof(int));
arr->cnt = 1;
arr->items[arr->cnt - 1] = 42;
asm volatile (""::"r"(arr));
return 0;
}
12:53:34 tmp$ clang -fsanitize=undefined ./test.c
12:53:36 tmp$ ./a.out
12:53:38 tmp$ echo $?
0
Or here is the IR generated for C program:
struct arr {
unsigned int cnt;
int items[] __attribute__((__counted_by__(cnt)));
};
void push(int i, struct arr *arr) {
arr->items[arr->cnt] = 42;
arr->cnt++;
}
Note the 'cnt' passed as a parameter to '@__ubsan_handle_out_of_bounds':
define dso_local void @push(i32 noundef %0, ptr noundef %1) local_unnamed_addr #0 !func_sanitize !3 {
...
%11 = load i32, ptr %1, align 4
%12 = zext i32 %11 to i64
tail call void @__ubsan_handle_out_of_bounds(ptr nonnull @6, i64 %12) #2, !nosanitize !4
[...]
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH] bpf: Annotate struct bpf_cand_cache with __counted_by()
2024-08-13 18:57 ` Alexei Starovoitov
2024-08-13 20:12 ` Eduard Zingerman
@ 2024-08-13 20:51 ` Thorsten Blum
2024-08-14 15:46 ` Alexei Starovoitov
1 sibling, 1 reply; 7+ messages in thread
From: Thorsten Blum @ 2024-08-13 20:51 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Martin KaFai Lau, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eddy Z, Song Liu, Yonghong Song, John Fastabend,
KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Kees Cook,
Gustavo A. R. Silva, bpf, LKML, linux-hardening
On 13. Aug 2024, at 20:57, Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
> On Tue, Aug 13, 2024 at 10:59 AM Thorsten Blum <thorsten.blum@toblux.com> wrote:
>> On 13. Aug 2024, at 18:28, Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
>>> On Tue, Aug 13, 2024 at 8:19 AM Thorsten Blum <thorsten.blum@toblux.com> wrote:
>>>>
>>>> Add the __counted_by compiler attribute to the flexible array member
>>>> cands to improve access bounds-checking via CONFIG_UBSAN_BOUNDS and
>>>> CONFIG_FORTIFY_SOURCE.
>>>>
>>>> Increment cnt before adding a new struct to the cands array.
>>>
>>> why? What happens otherwise?
>>
>> If you try to access cands->cands[cands->cnt] without incrementing
>> cands->cnt first, you're essentially accessing the array out of bounds
>> which will fail during runtime.
>
> What kind of error/warn do you see ?
> Is it runtime or compile time?
I get a runtime error with Clang 18 [3].
> Is this the only place?
I think so.
> what about:
> new_cands = kmemdup(cands, sizeof_cands(cands->cnt), GFP_KERNEL);
>
> cnt field gets copied with other fields.
> Can compiler/runtime catch that?
I think this is ok and there's nothing to catch.
> You can read more about it at [1] and [2].
>>
>>> Signed-off-by: Thorsten Blum <thorsten.blum@toblux.com>
>>>> ---
>>>> kernel/bpf/btf.c | 6 +++---
>>>> 1 file changed, 3 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
>>>> index 520f49f422fe..42bc70a56fcd 100644
>>>> --- a/kernel/bpf/btf.c
>>>> +++ b/kernel/bpf/btf.c
>>>> @@ -7240,7 +7240,7 @@ struct bpf_cand_cache {
>>>> struct {
>>>> const struct btf *btf;
>>>> u32 id;
>>>> - } cands[];
>>>> + } cands[] __counted_by(cnt);
>>>> };
>>>>
>>>> static DEFINE_MUTEX(cand_cache_mutex);
>>>> @@ -8784,9 +8784,9 @@ bpf_core_add_cands(struct bpf_cand_cache *cands, const struct btf *targ_btf,
>>>> memcpy(new_cands, cands, sizeof_cands(cands->cnt));
>>>> bpf_free_cands(cands);
>>>> cands = new_cands;
>>>> - cands->cands[cands->cnt].btf = targ_btf;
>>>> - cands->cands[cands->cnt].id = i;
>>>> cands->cnt++;
>>>> + cands->cands[cands->cnt - 1].btf = targ_btf;
>>>> + cands->cands[cands->cnt - 1].id = i;
>>>> }
>>>> return cands;
>>>> }
>>>> --
>>>> 2.46.0
>>>>
>>
>> [1] https://opensource.googleblog.com/2024/07/bounds-checking-flexible-array-members.html
>> [2] https://embeddedor.com/blog/2024/06/18/how-to-use-the-new-counted_by-attribute-in-c-and-linux/
[3] https://godbolt.org/z/cKee95777
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH] bpf: Annotate struct bpf_cand_cache with __counted_by()
2024-08-13 20:51 ` Thorsten Blum
@ 2024-08-14 15:46 ` Alexei Starovoitov
0 siblings, 0 replies; 7+ messages in thread
From: Alexei Starovoitov @ 2024-08-14 15:46 UTC (permalink / raw)
To: Thorsten Blum
Cc: Martin KaFai Lau, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eddy Z, Song Liu, Yonghong Song, John Fastabend,
KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Kees Cook,
Gustavo A. R. Silva, bpf, LKML, linux-hardening
On Tue, Aug 13, 2024 at 1:51 PM Thorsten Blum <thorsten.blum@toblux.com> wrote:
>
> On 13. Aug 2024, at 20:57, Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
> > On Tue, Aug 13, 2024 at 10:59 AM Thorsten Blum <thorsten.blum@toblux.com> wrote:
> >> On 13. Aug 2024, at 18:28, Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
> >>> On Tue, Aug 13, 2024 at 8:19 AM Thorsten Blum <thorsten.blum@toblux.com> wrote:
> >>>>
> >>>> Add the __counted_by compiler attribute to the flexible array member
> >>>> cands to improve access bounds-checking via CONFIG_UBSAN_BOUNDS and
> >>>> CONFIG_FORTIFY_SOURCE.
> >>>>
> >>>> Increment cnt before adding a new struct to the cands array.
> >>>
> >>> why? What happens otherwise?
> >>
> >> If you try to access cands->cands[cands->cnt] without incrementing
> >> cands->cnt first, you're essentially accessing the array out of bounds
> >> which will fail during runtime.
> >
> > What kind of error/warn do you see ?
> > Is it runtime or compile time?
>
> I get a runtime error with Clang 18 [3].
...
> [3] https://godbolt.org/z/cKee95777
This is user space.
I'm not asking about generic description of the counted_by feature.
I want to see the actual runtime report from the kernel.
Can it even compile the kernel with -fsanitize=undefined ?
pw-bot: cr
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2024-08-14 15:46 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-08-13 15:17 [PATCH] bpf: Annotate struct bpf_cand_cache with __counted_by() Thorsten Blum
2024-08-13 16:28 ` Alexei Starovoitov
2024-08-13 17:59 ` Thorsten Blum
2024-08-13 18:57 ` Alexei Starovoitov
2024-08-13 20:12 ` Eduard Zingerman
2024-08-13 20:51 ` Thorsten Blum
2024-08-14 15:46 ` Alexei Starovoitov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®