diff mbox series

[bpf,2/2] bpf: add tests for PTR_TO_BTF_ID vs. null comparison

Message ID 20200630171241.2523875-1-yhs@fb.com
State Accepted
Delegated to: BPF Maintainers
Headers show
Series bpf: fix an incorrect branch elimination by verifier | expand

Commit Message

Yonghong Song June 30, 2020, 5:12 p.m. UTC
Add two tests for PTR_TO_BTF_ID vs. null ptr comparison,
one for PTR_TO_BTF_ID in the ctx structure and the
other for PTR_TO_BTF_ID after one level pointer chasing.
In both cases, the test ensures condition is not
removed.

For example, for this test
 struct bpf_fentry_test_t {
     struct bpf_fentry_test_t *a;
 };
 int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
 {
     if (arg == 0)
         test7_result = 1;
     return 0;
 }
Before the previous verifier change, we have xlated codes:
  int test7(long long unsigned int * ctx):
  ; int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
     0: (79) r1 = *(u64 *)(r1 +0)
  ; int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
     1: (b4) w0 = 0
     2: (95) exit
After the previous verifier change, we have:
  int test7(long long unsigned int * ctx):
  ; int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
     0: (79) r1 = *(u64 *)(r1 +0)
  ; if (arg == 0)
     1: (55) if r1 != 0x0 goto pc+4
  ; test7_result = 1;
     2: (18) r1 = map[id:6][0]+48
     4: (b7) r2 = 1
     5: (7b) *(u64 *)(r1 +0) = r2
  ; int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
     6: (b4) w0 = 0
     7: (95) exit

Cc: Andrii Nakryiko <andriin@fb.com>
Cc: John Fastabend <john.fastabend@gmail.com>
Cc: Wenbo Zhang <ethercflow@gmail.com>
Signed-off-by: Yonghong Song <yhs@fb.com>
---
 net/bpf/test_run.c                            | 19 +++++++++++++++-
 .../selftests/bpf/prog_tests/fentry_fexit.c   |  2 +-
 .../testing/selftests/bpf/progs/fentry_test.c | 22 +++++++++++++++++++
 .../testing/selftests/bpf/progs/fexit_test.c  | 22 +++++++++++++++++++
 4 files changed, 63 insertions(+), 2 deletions(-)

Comments

John Fastabend June 30, 2020, 6:43 p.m. UTC | #1
Yonghong Song wrote:
> Add two tests for PTR_TO_BTF_ID vs. null ptr comparison,
> one for PTR_TO_BTF_ID in the ctx structure and the
> other for PTR_TO_BTF_ID after one level pointer chasing.
> In both cases, the test ensures condition is not
> removed.
> 
> For example, for this test
>  struct bpf_fentry_test_t {
>      struct bpf_fentry_test_t *a;
>  };
>  int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
>  {
>      if (arg == 0)
>          test7_result = 1;
>      return 0;
>  }
> Before the previous verifier change, we have xlated codes:
>   int test7(long long unsigned int * ctx):
>   ; int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
>      0: (79) r1 = *(u64 *)(r1 +0)
>   ; int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
>      1: (b4) w0 = 0
>      2: (95) exit
> After the previous verifier change, we have:
>   int test7(long long unsigned int * ctx):
>   ; int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
>      0: (79) r1 = *(u64 *)(r1 +0)
>   ; if (arg == 0)
>      1: (55) if r1 != 0x0 goto pc+4
>   ; test7_result = 1;
>      2: (18) r1 = map[id:6][0]+48
>      4: (b7) r2 = 1
>      5: (7b) *(u64 *)(r1 +0) = r2
>   ; int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
>      6: (b4) w0 = 0
>      7: (95) exit
> 
> Cc: Andrii Nakryiko <andriin@fb.com>
> Cc: John Fastabend <john.fastabend@gmail.com>
> Cc: Wenbo Zhang <ethercflow@gmail.com>
> Signed-off-by: Yonghong Song <yhs@fb.com>
> ---

Thanks.

Acked-by: John Fastabend <john.fastabend@gmail.com>
Andrii Nakryiko June 30, 2020, 7:23 p.m. UTC | #2
On Tue, Jun 30, 2020 at 11:46 AM Yonghong Song <yhs@fb.com> wrote:
>
> Add two tests for PTR_TO_BTF_ID vs. null ptr comparison,
> one for PTR_TO_BTF_ID in the ctx structure and the
> other for PTR_TO_BTF_ID after one level pointer chasing.
> In both cases, the test ensures condition is not
> removed.
>
> For example, for this test
>  struct bpf_fentry_test_t {
>      struct bpf_fentry_test_t *a;
>  };
>  int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
>  {
>      if (arg == 0)
>          test7_result = 1;
>      return 0;
>  }
> Before the previous verifier change, we have xlated codes:
>   int test7(long long unsigned int * ctx):
>   ; int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
>      0: (79) r1 = *(u64 *)(r1 +0)
>   ; int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
>      1: (b4) w0 = 0
>      2: (95) exit
> After the previous verifier change, we have:
>   int test7(long long unsigned int * ctx):
>   ; int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
>      0: (79) r1 = *(u64 *)(r1 +0)
>   ; if (arg == 0)
>      1: (55) if r1 != 0x0 goto pc+4
>   ; test7_result = 1;
>      2: (18) r1 = map[id:6][0]+48
>      4: (b7) r2 = 1
>      5: (7b) *(u64 *)(r1 +0) = r2
>   ; int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
>      6: (b4) w0 = 0
>      7: (95) exit
>
> Cc: Andrii Nakryiko <andriin@fb.com>
> Cc: John Fastabend <john.fastabend@gmail.com>
> Cc: Wenbo Zhang <ethercflow@gmail.com>
> Signed-off-by: Yonghong Song <yhs@fb.com>
> ---

LGTM, two nits below.

Acked-by: Andrii Nakryiko <andriin@fb.com>

>  net/bpf/test_run.c                            | 19 +++++++++++++++-
>  .../selftests/bpf/prog_tests/fentry_fexit.c   |  2 +-
>  .../testing/selftests/bpf/progs/fentry_test.c | 22 +++++++++++++++++++
>  .../testing/selftests/bpf/progs/fexit_test.c  | 22 +++++++++++++++++++
>  4 files changed, 63 insertions(+), 2 deletions(-)
>

[...]

> diff --git a/tools/testing/selftests/bpf/progs/fentry_test.c b/tools/testing/selftests/bpf/progs/fentry_test.c
> index 9365b686f84b..5f645fdaba6f 100644
> --- a/tools/testing/selftests/bpf/progs/fentry_test.c
> +++ b/tools/testing/selftests/bpf/progs/fentry_test.c
> @@ -55,3 +55,25 @@ int BPF_PROG(test6, __u64 a, void *b, short c, int d, void * e, __u64 f)
>                 e == (void *)20 && f == 21;
>         return 0;
>  }
> +
> +struct bpf_fentry_test_t {
> +       struct bpf_fentry_test_t *a;
> +};

nit: __attribute__((preserve_access_index)) ?

> +
> +__u64 test7_result = 0;
> +SEC("fentry/bpf_fentry_test7")
> +int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
> +{
> +       if (arg == 0)
> +               test7_result = 1;
> +       return 0;
> +}
> +
> +__u64 test8_result = 0;
> +SEC("fentry/bpf_fentry_test8")
> +int BPF_PROG(test8, struct bpf_fentry_test_t *arg)
> +{
> +       if (arg->a == 0)
> +               test8_result = 1;
> +       return 0;
> +}
> diff --git a/tools/testing/selftests/bpf/progs/fexit_test.c b/tools/testing/selftests/bpf/progs/fexit_test.c
> index bd1e17d8024c..0952affb22a6 100644
> --- a/tools/testing/selftests/bpf/progs/fexit_test.c
> +++ b/tools/testing/selftests/bpf/progs/fexit_test.c
> @@ -56,3 +56,25 @@ int BPF_PROG(test6, __u64 a, void *b, short c, int d, void *e, __u64 f, int ret)
>                 e == (void *)20 && f == 21 && ret == 111;
>         return 0;
>  }
> +
> +struct bpf_fentry_test_t {
> +       struct bpf_fentry_test *a;
> +};

same nit

> +
> +__u64 test7_result = 0;
> +SEC("fexit/bpf_fentry_test7")
> +int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
> +{
> +       if (arg == 0)
> +               test7_result = 1;
> +       return 0;
> +}
> +
> +__u64 test8_result = 0;
> +SEC("fexit/bpf_fentry_test8")
> +int BPF_PROG(test8, struct bpf_fentry_test_t *arg)
> +{
> +       if (arg->a == 0)
> +               test8_result = 1;
> +       return 0;
> +}
> --
> 2.24.1
>
Yonghong Song June 30, 2020, 8:13 p.m. UTC | #3
On 6/30/20 12:23 PM, Andrii Nakryiko wrote:
> On Tue, Jun 30, 2020 at 11:46 AM Yonghong Song <yhs@fb.com> wrote:
>>
>> Add two tests for PTR_TO_BTF_ID vs. null ptr comparison,
>> one for PTR_TO_BTF_ID in the ctx structure and the
>> other for PTR_TO_BTF_ID after one level pointer chasing.
>> In both cases, the test ensures condition is not
>> removed.
>>
>> For example, for this test
>>   struct bpf_fentry_test_t {
>>       struct bpf_fentry_test_t *a;
>>   };
>>   int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
>>   {
>>       if (arg == 0)
>>           test7_result = 1;
>>       return 0;
>>   }
>> Before the previous verifier change, we have xlated codes:
>>    int test7(long long unsigned int * ctx):
>>    ; int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
>>       0: (79) r1 = *(u64 *)(r1 +0)
>>    ; int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
>>       1: (b4) w0 = 0
>>       2: (95) exit
>> After the previous verifier change, we have:
>>    int test7(long long unsigned int * ctx):
>>    ; int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
>>       0: (79) r1 = *(u64 *)(r1 +0)
>>    ; if (arg == 0)
>>       1: (55) if r1 != 0x0 goto pc+4
>>    ; test7_result = 1;
>>       2: (18) r1 = map[id:6][0]+48
>>       4: (b7) r2 = 1
>>       5: (7b) *(u64 *)(r1 +0) = r2
>>    ; int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
>>       6: (b4) w0 = 0
>>       7: (95) exit
>>
>> Cc: Andrii Nakryiko <andriin@fb.com>
>> Cc: John Fastabend <john.fastabend@gmail.com>
>> Cc: Wenbo Zhang <ethercflow@gmail.com>
>> Signed-off-by: Yonghong Song <yhs@fb.com>
>> ---
> 
> LGTM, two nits below.
> 
> Acked-by: Andrii Nakryiko <andriin@fb.com>
> 
>>   net/bpf/test_run.c                            | 19 +++++++++++++++-
>>   .../selftests/bpf/prog_tests/fentry_fexit.c   |  2 +-
>>   .../testing/selftests/bpf/progs/fentry_test.c | 22 +++++++++++++++++++
>>   .../testing/selftests/bpf/progs/fexit_test.c  | 22 +++++++++++++++++++
>>   4 files changed, 63 insertions(+), 2 deletions(-)
>>
> 
> [...]
> 
>> diff --git a/tools/testing/selftests/bpf/progs/fentry_test.c b/tools/testing/selftests/bpf/progs/fentry_test.c
>> index 9365b686f84b..5f645fdaba6f 100644
>> --- a/tools/testing/selftests/bpf/progs/fentry_test.c
>> +++ b/tools/testing/selftests/bpf/progs/fentry_test.c
>> @@ -55,3 +55,25 @@ int BPF_PROG(test6, __u64 a, void *b, short c, int d, void * e, __u64 f)
>>                  e == (void *)20 && f == 21;
>>          return 0;
>>   }
>> +
>> +struct bpf_fentry_test_t {
>> +       struct bpf_fentry_test_t *a;
>> +};
> 
> nit: __attribute__((preserve_access_index)) ?

Yes. Why not. Will send a followup once the patch circulates back to 
bpf-next.

> 
>> +
>> +__u64 test7_result = 0;
>> +SEC("fentry/bpf_fentry_test7")
>> +int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
>> +{
>> +       if (arg == 0)
>> +               test7_result = 1;
>> +       return 0;
>> +}
>> +
[...]
diff mbox series

Patch

diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c
index bfd4ccd80847..b03c469cd01f 100644
--- a/net/bpf/test_run.c
+++ b/net/bpf/test_run.c
@@ -147,6 +147,20 @@  int noinline bpf_fentry_test6(u64 a, void *b, short c, int d, void *e, u64 f)
 	return a + (long)b + c + d + (long)e + f;
 }
 
+struct bpf_fentry_test_t {
+	struct bpf_fentry_test_t *a;
+};
+
+int noinline bpf_fentry_test7(struct bpf_fentry_test_t *arg)
+{
+	return (long)arg;
+}
+
+int noinline bpf_fentry_test8(struct bpf_fentry_test_t *arg)
+{
+	return (long)arg->a;
+}
+
 int noinline bpf_modify_return_test(int a, int *b)
 {
 	*b += 1;
@@ -185,6 +199,7 @@  int bpf_prog_test_run_tracing(struct bpf_prog *prog,
 			      const union bpf_attr *kattr,
 			      union bpf_attr __user *uattr)
 {
+	struct bpf_fentry_test_t arg = {};
 	u16 side_effect = 0, ret = 0;
 	int b = 2, err = -EFAULT;
 	u32 retval = 0;
@@ -197,7 +212,9 @@  int bpf_prog_test_run_tracing(struct bpf_prog *prog,
 		    bpf_fentry_test3(4, 5, 6) != 15 ||
 		    bpf_fentry_test4((void *)7, 8, 9, 10) != 34 ||
 		    bpf_fentry_test5(11, (void *)12, 13, 14, 15) != 65 ||
-		    bpf_fentry_test6(16, (void *)17, 18, 19, (void *)20, 21) != 111)
+		    bpf_fentry_test6(16, (void *)17, 18, 19, (void *)20, 21) != 111 ||
+		    bpf_fentry_test7((struct bpf_fentry_test_t *)0) != 0 ||
+		    bpf_fentry_test8(&arg) != 0)
 			goto out;
 		break;
 	case BPF_MODIFY_RETURN:
diff --git a/tools/testing/selftests/bpf/prog_tests/fentry_fexit.c b/tools/testing/selftests/bpf/prog_tests/fentry_fexit.c
index 83493bd5745c..109d0345a2be 100644
--- a/tools/testing/selftests/bpf/prog_tests/fentry_fexit.c
+++ b/tools/testing/selftests/bpf/prog_tests/fentry_fexit.c
@@ -36,7 +36,7 @@  void test_fentry_fexit(void)
 	fentry_res = (__u64 *)fentry_skel->bss;
 	fexit_res = (__u64 *)fexit_skel->bss;
 	printf("%lld\n", fentry_skel->bss->test1_result);
-	for (i = 0; i < 6; i++) {
+	for (i = 0; i < 8; i++) {
 		CHECK(fentry_res[i] != 1, "result",
 		      "fentry_test%d failed err %lld\n", i + 1, fentry_res[i]);
 		CHECK(fexit_res[i] != 1, "result",
diff --git a/tools/testing/selftests/bpf/progs/fentry_test.c b/tools/testing/selftests/bpf/progs/fentry_test.c
index 9365b686f84b..5f645fdaba6f 100644
--- a/tools/testing/selftests/bpf/progs/fentry_test.c
+++ b/tools/testing/selftests/bpf/progs/fentry_test.c
@@ -55,3 +55,25 @@  int BPF_PROG(test6, __u64 a, void *b, short c, int d, void * e, __u64 f)
 		e == (void *)20 && f == 21;
 	return 0;
 }
+
+struct bpf_fentry_test_t {
+	struct bpf_fentry_test_t *a;
+};
+
+__u64 test7_result = 0;
+SEC("fentry/bpf_fentry_test7")
+int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
+{
+	if (arg == 0)
+		test7_result = 1;
+	return 0;
+}
+
+__u64 test8_result = 0;
+SEC("fentry/bpf_fentry_test8")
+int BPF_PROG(test8, struct bpf_fentry_test_t *arg)
+{
+	if (arg->a == 0)
+		test8_result = 1;
+	return 0;
+}
diff --git a/tools/testing/selftests/bpf/progs/fexit_test.c b/tools/testing/selftests/bpf/progs/fexit_test.c
index bd1e17d8024c..0952affb22a6 100644
--- a/tools/testing/selftests/bpf/progs/fexit_test.c
+++ b/tools/testing/selftests/bpf/progs/fexit_test.c
@@ -56,3 +56,25 @@  int BPF_PROG(test6, __u64 a, void *b, short c, int d, void *e, __u64 f, int ret)
 		e == (void *)20 && f == 21 && ret == 111;
 	return 0;
 }
+
+struct bpf_fentry_test_t {
+	struct bpf_fentry_test *a;
+};
+
+__u64 test7_result = 0;
+SEC("fexit/bpf_fentry_test7")
+int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
+{
+	if (arg == 0)
+		test7_result = 1;
+	return 0;
+}
+
+__u64 test8_result = 0;
+SEC("fexit/bpf_fentry_test8")
+int BPF_PROG(test8, struct bpf_fentry_test_t *arg)
+{
+	if (arg->a == 0)
+		test8_result = 1;
+	return 0;
+}