diff mbox series

fix array-index-out-of-bounds in bpf_prog_select_runtime

Message ID 20240505014641.203643-1-cam.alvarez.i@gmail.com (mailing list archive)
State Changes Requested
Delegated to: BPF
Headers show
Series fix array-index-out-of-bounds in bpf_prog_select_runtime | expand

Checks

Context Check Description
bpf/vmtest-bpf-next-VM_Test-0 success Logs for Lint
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-2 success Logs for Unittests
bpf/vmtest-bpf-next-VM_Test-3 success Logs for Validate matrix.py
bpf/vmtest-bpf-next-VM_Test-5 success Logs for aarch64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-4 success Logs for aarch64-gcc / build / build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-9 success Logs for aarch64-gcc / test (test_verifier, false, 360) / test_verifier on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-11 success Logs for s390x-gcc / build / build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-10 success Logs for aarch64-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-12 success Logs for s390x-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-13 success Logs for s390x-gcc / test (test_maps, false, 360) / test_maps on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-17 success Logs for s390x-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-16 success Logs for s390x-gcc / test (test_verifier, false, 360) / test_verifier on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-19 success Logs for x86_64-gcc / build / build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-18 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-20 success Logs for x86_64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-21 success Logs for x86_64-gcc / test (test_maps, false, 360) / test_maps on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-26 success Logs for x86_64-gcc / test (test_verifier, false, 360) / test_verifier on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-28 success Logs for x86_64-llvm-17 / build / build for x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-30 success Logs for x86_64-llvm-17 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-29 success Logs for x86_64-llvm-17 / build-release / build for x86_64 with llvm-17 and -O2 optimization
bpf/vmtest-bpf-next-VM_Test-33 success Logs for x86_64-llvm-17 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-34 success Logs for x86_64-llvm-17 / veristat
bpf/vmtest-bpf-next-VM_Test-36 success Logs for x86_64-llvm-18 / build-release / build for x86_64 with llvm-18 and -O2 optimization
bpf/vmtest-bpf-next-VM_Test-37 success Logs for x86_64-llvm-18 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-35 success Logs for x86_64-llvm-18 / build / build for x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-41 success Logs for x86_64-llvm-18 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-42 success Logs for x86_64-llvm-18 / veristat
bpf/vmtest-bpf-next-PR fail PR summary
bpf/vmtest-bpf-next-VM_Test-6 success Logs for aarch64-gcc / test (test_maps, false, 360) / test_maps on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-7 fail Logs for aarch64-gcc / test (test_progs, false, 360) / test_progs on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-8 fail Logs for aarch64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-14 fail Logs for s390x-gcc / test (test_progs, false, 360) / test_progs on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-15 fail Logs for s390x-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-23 fail Logs for x86_64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-22 fail Logs for x86_64-gcc / test (test_progs, false, 360) / test_progs on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-24 success Logs for x86_64-gcc / test (test_progs_no_alu32_parallel, true, 30) / test_progs_no_alu32_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-25 success Logs for x86_64-gcc / test (test_progs_parallel, true, 30) / test_progs_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-27 fail Logs for x86_64-gcc / veristat / veristat on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-32 fail Logs for x86_64-llvm-17 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-31 fail Logs for x86_64-llvm-17 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-38 fail Logs for x86_64-llvm-18 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-40 fail Logs for x86_64-llvm-18 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-39 fail Logs for x86_64-llvm-18 / test (test_progs_cpuv4, false, 360) / test_progs_cpuv4 on x86_64 with llvm-18
netdev/series_format warning Single patches do not need cover letters; Target tree name not specified in the subject
netdev/tree_selection success Guessed tree name to be net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 938 this patch: 938
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers warning 10 maintainers not CCed: kpsingh@kernel.org john.fastabend@gmail.com andrii@kernel.org jolsa@kernel.org eddyz87@gmail.com song@kernel.org yonghong.song@linux.dev martin.lau@linux.dev haoluo@google.com sdf@google.com
netdev/build_clang success Errors and warnings before: 938 this patch: 938
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 949 this patch: 949
netdev/checkpatch fail ERROR: code indent should use tabs where possible WARNING: please, no spaces at the start of a line
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Camila Alvarez Inostroza May 5, 2024, 1:46 a.m. UTC
The error indicates that the verifier is letting through a program with
a stack depth bigger than 512.

This is due to the verifier not checking the stack depth after
instruction rewrites are perfomed. For example, the MAY_GOTO instruction
adds 8 bytes to the stack, which means that if the stack at the moment
was already 512 bytes it would overflow after rewriting the instruction.

The fix involves adding a stack depth check after all instruction
rewrites are performed.

Reported-by: syzbot+d2a2c639d03ac200a4f1@syzkaller.appspotmail.com
Signed-off-by: Camila Alvarez <cam.alvarez.i@gmail.com>
---
 kernel/bpf/verifier.c | 4 ++++
 1 file changed, 4 insertions(+)

Comments

Alexei Starovoitov May 5, 2024, 8:21 a.m. UTC | #1
On Sat, May 4, 2024 at 6:49 PM Camila Alvarez <cam.alvarez.i@gmail.com> wrote:
>
> The error indicates that the verifier is letting through a program with
> a stack depth bigger than 512.
>
> This is due to the verifier not checking the stack depth after
> instruction rewrites are perfomed. For example, the MAY_GOTO instruction
> adds 8 bytes to the stack, which means that if the stack at the moment
> was already 512 bytes it would overflow after rewriting the instruction.

This is by design. may_goto and other constructs like bpf_loop
inlining can consume a few words above 512 limit.

> The fix involves adding a stack depth check after all instruction
> rewrites are performed.
>
> Reported-by: syzbot+d2a2c639d03ac200a4f1@syzkaller.appspotmail.com

This syzbot report is likely unrelated.
It says that it bisected it to may_goto, but it has this report
before may_goto was introduced, so bisection is incorrect.

pw-bot: cr

> Signed-off-by: Camila Alvarez <cam.alvarez.i@gmail.com>
> ---
>  kernel/bpf/verifier.c | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 63749ad5ac6b..a9e23b6b8e8f 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -21285,6 +21285,10 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3
>         if (ret == 0)
>                 ret = do_misc_fixups(env);
>
> +        /* max stack depth verification must be done after rewrites as well */
> +        if (ret == 0)
> +                ret = check_max_stack_depth(env);
> +
>         /* do 32-bit optimization after insn patching has done so those patched
>          * insns could be handled correctly.
>          */
> --
> 2.34.1
>
Camila Alvarez Inostroza May 5, 2024, 11:18 p.m. UTC | #2
On Sun, 5 May 2024, Alexei Starovoitov wrote:

> On Sat, May 4, 2024 at 6:49 PM Camila Alvarez <cam.alvarez.i@gmail.com> wrote:
>>
>> The error indicates that the verifier is letting through a program with
>> a stack depth bigger than 512.
>>
>> This is due to the verifier not checking the stack depth after
>> instruction rewrites are perfomed. For example, the MAY_GOTO instruction
>> adds 8 bytes to the stack, which means that if the stack at the moment
>> was already 512 bytes it would overflow after rewriting the instruction.
>
> This is by design. may_goto and other constructs like bpf_loop
> inlining can consume a few words above 512 limit.
>

Is this the only case where the verifier should allow the stack to go over 
the 512 limit? If that's the case, maybe we could use the extra stack 
depth to store how much the rewrites affect the stack depth? This would 
only be used to obtain the correct interpreter when 
CONFIG_BPF_JIT_ALWAYS_ON is not set.
That would allow choosing the interpreter by considering the stack depth 
before the rewrites.

>> The fix involves adding a stack depth check after all instruction
>> rewrites are performed.
>>
>> Reported-by: syzbot+d2a2c639d03ac200a4f1@syzkaller.appspotmail.com
>
> This syzbot report is likely unrelated.
> It says that it bisected it to may_goto, but it has this report
> before may_goto was introduced, so bisection is incorrect.
>
> pw-bot: cr

I can see that may_goto was introduced on march 6th, and the first report 
was on march 13th. Is there any report I'm missing?

>
>> Signed-off-by: Camila Alvarez <cam.alvarez.i@gmail.com>
>> ---
>>  kernel/bpf/verifier.c | 4 ++++
>>  1 file changed, 4 insertions(+)
>>
>> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
>> index 63749ad5ac6b..a9e23b6b8e8f 100644
>> --- a/kernel/bpf/verifier.c
>> +++ b/kernel/bpf/verifier.c
>> @@ -21285,6 +21285,10 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3
>>         if (ret == 0)
>>                 ret = do_misc_fixups(env);
>>
>> +        /* max stack depth verification must be done after rewrites as well */
>> +        if (ret == 0)
>> +                ret = check_max_stack_depth(env);
>> +
>>         /* do 32-bit optimization after insn patching has done so those patched
>>          * insns could be handled correctly.
>>          */
>> --
>> 2.34.1
>>
>
Alexei Starovoitov May 6, 2024, 11:35 p.m. UTC | #3
On Sun, May 5, 2024 at 4:18 PM Camila Alvarez Inostroza
<cam.alvarez.i@gmail.com> wrote:
>
>
>
> On Sun, 5 May 2024, Alexei Starovoitov wrote:
>
> > On Sat, May 4, 2024 at 6:49 PM Camila Alvarez <cam.alvarez.i@gmail.com> wrote:
> >>
> >> The error indicates that the verifier is letting through a program with
> >> a stack depth bigger than 512.
> >>
> >> This is due to the verifier not checking the stack depth after
> >> instruction rewrites are perfomed. For example, the MAY_GOTO instruction
> >> adds 8 bytes to the stack, which means that if the stack at the moment
> >> was already 512 bytes it would overflow after rewriting the instruction.
> >
> > This is by design. may_goto and other constructs like bpf_loop
> > inlining can consume a few words above 512 limit.
> >
>
> Is this the only case where the verifier should allow the stack to go over
> the 512 limit? If that's the case, maybe we could use the extra stack
> depth to store how much the rewrites affect the stack depth? This would
> only be used to obtain the correct interpreter when
> CONFIG_BPF_JIT_ALWAYS_ON is not set.
> That would allow choosing the interpreter by considering the stack depth
> before the rewrites.
>
> >> The fix involves adding a stack depth check after all instruction
> >> rewrites are performed.
> >>
> >> Reported-by: syzbot+d2a2c639d03ac200a4f1@syzkaller.appspotmail.com
> >
> > This syzbot report is likely unrelated.
> > It says that it bisected it to may_goto, but it has this report
> > before may_goto was introduced, so bisection is incorrect.
> >
> > pw-bot: cr
>
> I can see that may_goto was introduced on march 6th, and the first report
> was on march 13th. Is there any report I'm missing?

Could you please craft a selftest for this issue then?
It will be much easier to reason about the fix.
We can either add another interpreter to interpreters_args[]
or just gate may_goto with prog->jit_requested.
diff mbox series

Patch

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 63749ad5ac6b..a9e23b6b8e8f 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -21285,6 +21285,10 @@  int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3
 	if (ret == 0)
 		ret = do_misc_fixups(env);
 
+        /* max stack depth verification must be done after rewrites as well */
+        if (ret == 0)
+                ret = check_max_stack_depth(env);
+
 	/* do 32-bit optimization after insn patching has done so those patched
 	 * insns could be handled correctly.
 	 */