diff mbox series

bpf: Fix incorrect precision backtracking

Message ID 20241101195702.2926731-1-tao.lyu@epfl.ch (mailing list archive)
State Changes Requested
Delegated to: BPF
Headers show
Series bpf: Fix incorrect precision backtracking | expand

Checks

Context Check Description
bpf/vmtest-bpf-next-PR success PR summary
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-0 success Logs for Lint
bpf/vmtest-bpf-next-VM_Test-5 success Logs for aarch64-gcc / build-release
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: 3 this patch: 3
netdev/build_tools success Errors and warnings before: 2 (+0) this patch: 2 (+0)
netdev/cc_maintainers warning 9 maintainers not CCed: sdf@fomichev.me shuah@kernel.org kpsingh@kernel.org jose.marchesi@oracle.com john.fastabend@gmail.com eddyz87@gmail.com mykolal@fb.com linux-kselftest@vger.kernel.org jolsa@kernel.org
netdev/build_clang success Errors and warnings before: 3 this patch: 3
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: 14 this patch: 14
netdev/checkpatch fail ERROR: "(foo*)" should be "(foo *)" ERROR: code indent should use tabs where possible WARNING: braces {} are not necessary for single statement blocks 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
bpf/vmtest-bpf-next-VM_Test-4 success Logs for aarch64-gcc / build / build for aarch64 with gcc
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-10 success Logs for aarch64-gcc / veristat
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-13 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-12 success Logs for s390x-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-15 success Logs for x86_64-gcc / build-release
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-11 success Logs for s390x-gcc / build / build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-14 pending 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-16 success Logs for s390x-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-17 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-18 success Logs for x86_64-gcc / build / build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-20 pending Logs for x86_64-gcc / test (test_maps, false, 360) / test_maps on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-22 pending 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-19 success Logs for x86_64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-21 pending Logs for x86_64-gcc / test (test_progs, false, 360) / test_progs on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-23 pending 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 pending Logs for x86_64-gcc / test (test_verifier, false, 360) / test_verifier on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-24 pending 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-28 success Logs for x86_64-llvm-17 / build-release / build for x86_64 with llvm-17-O2
bpf/vmtest-bpf-next-VM_Test-26 pending Logs for x86_64-gcc / veristat / veristat on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-27 success Logs for x86_64-llvm-17 / build / build for x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-31 pending 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-29 pending 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-30 pending 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-33 success Logs for x86_64-llvm-17 / veristat
bpf/vmtest-bpf-next-VM_Test-32 pending 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-18 / build / build for x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-37 pending 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-35 success Logs for x86_64-llvm-18 / build-release / build for x86_64 with llvm-18-O2
bpf/vmtest-bpf-next-VM_Test-36 pending 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-40 pending 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-38 pending Logs for x86_64-llvm-18 / test (test_progs_cpuv4, false, 360) / test_progs_cpuv4 on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-41 success Logs for x86_64-llvm-18 / veristat
bpf/vmtest-bpf-next-VM_Test-39 pending Logs for x86_64-llvm-18 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-18

Commit Message

Tao Lyu Nov. 1, 2024, 7:57 p.m. UTC
Hi,

The process_iter_arg check function misses the type check on the iter
args, which leads to any pointer types can be passed as iter args.

As the attached testcase shows, when I pass a ptr_to_map_value whose
offset is 0, process_iter_arg still regards it as a stack pointer and
use its offset to check the stack slot types.

In this case, as long as the stack slot types matched with the
ptr_to_map_value offset is correct, then checks can be bypassed.

I attached the fix, which checks if the argument type is stack pointer.

Please let me know if this fix might be incomplete.
I'm happy to revise it.

Best,
Tao

Signed-off-by: Tao Lyu <tao.lyu@epfl.ch>
---
 kernel/bpf/verifier.c                     |  6 ++++++
 tools/testing/selftests/bpf/progs/iters.c | 23 +++++++++++++++++++++++
 2 files changed, 29 insertions(+)

Comments

Alexei Starovoitov Nov. 1, 2024, 8:22 p.m. UTC | #1
On Fri, Nov 1, 2024 at 1:04 PM Tao Lyu <tao.lyu@epfl.ch> wrote:
>
> Hi,
>
> The process_iter_arg check function misses the type check on the iter
> args, which leads to any pointer types can be passed as iter args.
>
> As the attached testcase shows, when I pass a ptr_to_map_value whose
> offset is 0, process_iter_arg still regards it as a stack pointer and
> use its offset to check the stack slot types.
>
> In this case, as long as the stack slot types matched with the
> ptr_to_map_value offset is correct, then checks can be bypassed.
>
> I attached the fix, which checks if the argument type is stack pointer.
>
> Please let me know if this fix might be incomplete.
> I'm happy to revise it.
>
> Best,
> Tao
>
> Signed-off-by: Tao Lyu <tao.lyu@epfl.ch>
> ---
>  kernel/bpf/verifier.c                     |  6 ++++++
>  tools/testing/selftests/bpf/progs/iters.c | 23 +++++++++++++++++++++++
>  2 files changed, 29 insertions(+)
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 797cf3ed32e0..bc968d2b76d9 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -8031,6 +8031,12 @@ static int process_iter_arg(struct bpf_verifier_env *env, int regno, int insn_id
>                 return -EINVAL;
>         }
>         t = btf_type_by_id(meta->btf, btf_id);
> +
> +       // Ensure the iter arg is a stack pointer

no c++ comments pls.

Also I believe Kumar sent a fix for this already.
It fell through the cracks.

Kumar,
please resend.

pw-bot: cr

> +       if (reg->type != PTR_TO_STACK) {
> +               verbose(env, "iter pointer should be the PTR_TO_STACK type\n");
> +               return -EINVAL;
> +       }
Kumar Kartikeya Dwivedi Nov. 3, 2024, 3:56 p.m. UTC | #2
On Fri, 1 Nov 2024 at 15:22, Alexei Starovoitov
<alexei.starovoitov@gmail.com> wrote:
>
> On Fri, Nov 1, 2024 at 1:04 PM Tao Lyu <tao.lyu@epfl.ch> wrote:
> >
> > Hi,
> >
> > The process_iter_arg check function misses the type check on the iter
> > args, which leads to any pointer types can be passed as iter args.
> >
> > As the attached testcase shows, when I pass a ptr_to_map_value whose
> > offset is 0, process_iter_arg still regards it as a stack pointer and
> > use its offset to check the stack slot types.
> >
> > In this case, as long as the stack slot types matched with the
> > ptr_to_map_value offset is correct, then checks can be bypassed.
> >
> > I attached the fix, which checks if the argument type is stack pointer.
> >
> > Please let me know if this fix might be incomplete.
> > I'm happy to revise it.
> >
> > Best,
> > Tao
> >
> > Signed-off-by: Tao Lyu <tao.lyu@epfl.ch>
> > ---
> >  kernel/bpf/verifier.c                     |  6 ++++++
> >  tools/testing/selftests/bpf/progs/iters.c | 23 +++++++++++++++++++++++
> >  2 files changed, 29 insertions(+)
> >
> > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> > index 797cf3ed32e0..bc968d2b76d9 100644
> > --- a/kernel/bpf/verifier.c
> > +++ b/kernel/bpf/verifier.c
> > @@ -8031,6 +8031,12 @@ static int process_iter_arg(struct bpf_verifier_env *env, int regno, int insn_id
> >                 return -EINVAL;
> >         }
> >         t = btf_type_by_id(meta->btf, btf_id);
> > +
> > +       // Ensure the iter arg is a stack pointer
>
> no c++ comments pls.
>
> Also I believe Kumar sent a fix for this already.
> It fell through the cracks.
>
> Kumar,
> please resend.

For this one, I didn't. I believe the one you're referring to was a
different bug, and yeah, that appears to have fallen through.
I handed it over to someone and they unfortunately happened to switch
jobs after that.
I'll sync with Tao and one of us will resend the other fix.

Tao,
For this, I think you need to fix your subject line as well, and add a
selftest covering this particular case.
Passing in e.g. a map value should be sufficient to test this behavior.

>
> pw-bot: cr
>
> > +       if (reg->type != PTR_TO_STACK) {
> > +               verbose(env, "iter pointer should be the PTR_TO_STACK type\n");
> > +               return -EINVAL;
> > +       }
diff mbox series

Patch

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 797cf3ed32e0..bc968d2b76d9 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -8031,6 +8031,12 @@  static int process_iter_arg(struct bpf_verifier_env *env, int regno, int insn_id
 		return -EINVAL;
 	}
 	t = btf_type_by_id(meta->btf, btf_id);
+
+	// Ensure the iter arg is a stack pointer
+	if (reg->type != PTR_TO_STACK) {
+		verbose(env, "iter pointer should be the PTR_TO_STACK type\n");
+		return -EINVAL;
+	}
 	nr_slots = t->size / BPF_REG_SIZE;
 
 	if (is_iter_new_kfunc(meta)) {
diff --git a/tools/testing/selftests/bpf/progs/iters.c b/tools/testing/selftests/bpf/progs/iters.c
index ef70b88bccb2..52078fc395fd 100644
--- a/tools/testing/selftests/bpf/progs/iters.c
+++ b/tools/testing/selftests/bpf/progs/iters.c
@@ -1486,4 +1486,27 @@  int iter_subprog_check_stacksafe(const void *ctx)
 	return 0;
 }
 
+SEC("raw_tp")
+__failure __msg("iter pointer should be the PTR_TO_STACK type")
+int iter_check_arg_type(const void *ctx)
+{
+        struct bpf_iter_num it;
+        int *v;
+
+        int *map_val = NULL;
+        int key = 0;
+
+        map_val = bpf_map_lookup_elem(&arr_map, &key);
+        if (!map_val)
+                return 0;
+
+        bpf_iter_num_new(&it, 0, 3);
+        while ((v = bpf_iter_num_next((struct bpf_iter_num*)map_val))) {
+                bpf_printk("ITER_BASIC: E1 VAL: v=%d", *v);
+        }
+        bpf_iter_num_destroy(&it);
+
+        return 0;
+}
+
 char _license[] SEC("license") = "GPL";