* [PATCH bpf-next v2 0/2] bpf: permits pointers on stack for helper calls
@ 2020-12-10 1:33 Yonghong Song
2020-12-10 1:33 ` [PATCH bpf-next v2 1/2] " Yonghong Song
2020-12-10 1:33 ` [PATCH bpf-next v2 2/2] selftests/bpf: add a test for ptr_to_map_value on stack for helper access Yonghong Song
0 siblings, 2 replies; 7+ messages in thread
From: Yonghong Song @ 2020-12-10 1:33 UTC (permalink / raw)
To: bpf; +Cc: Alexei Starovoitov, Daniel Borkmann, kernel-team
This patch permits pointers on stack for helper calls if permission is
granted. Patch #1 described the detailed usecase and Patch #2
added a test.
Changelog:
v1 -> v2:
- fix a verifier test failure due to verifier change.
Yonghong Song (2):
bpf: permits pointers on stack for helper calls
selftests/bpf: add a test for ptr_to_map_value on stack for helper
access
kernel/bpf/verifier.c | 3 ++-
tools/testing/selftests/bpf/progs/bpf_iter_task.c | 3 ++-
tools/testing/selftests/bpf/verifier/unpriv.c | 5 +++--
3 files changed, 7 insertions(+), 4 deletions(-)
--
2.24.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH bpf-next v2 1/2] bpf: permits pointers on stack for helper calls
2020-12-10 1:33 [PATCH bpf-next v2 0/2] bpf: permits pointers on stack for helper calls Yonghong Song
@ 2020-12-10 1:33 ` Yonghong Song
2020-12-10 17:18 ` Song Liu
2020-12-11 0:10 ` Daniel Borkmann
2020-12-10 1:33 ` [PATCH bpf-next v2 2/2] selftests/bpf: add a test for ptr_to_map_value on stack for helper access Yonghong Song
1 sibling, 2 replies; 7+ messages in thread
From: Yonghong Song @ 2020-12-10 1:33 UTC (permalink / raw)
To: bpf; +Cc: Alexei Starovoitov, Daniel Borkmann, kernel-team, Song Liu
Currently, when checking stack memory accessed by helper calls,
for spills, only PTR_TO_BTF_ID and SCALAR_VALUE are
allowed.
Song discovered an issue where the below bpf program
int dump_task(struct bpf_iter__task *ctx)
{
struct seq_file *seq = ctx->meta->seq;
static char[] info = "abc";
BPF_SEQ_PRINTF(seq, "%s\n", info);
return 0;
}
may cause a verifier failure.
The verifier output looks like:
; struct seq_file *seq = ctx->meta->seq;
1: (79) r1 = *(u64 *)(r1 +0)
; BPF_SEQ_PRINTF(seq, "%s\n", info);
2: (18) r2 = 0xffff9054400f6000
4: (7b) *(u64 *)(r10 -8) = r2
5: (bf) r4 = r10
;
6: (07) r4 += -8
; BPF_SEQ_PRINTF(seq, "%s\n", info);
7: (18) r2 = 0xffff9054400fe000
9: (b4) w3 = 4
10: (b4) w5 = 8
11: (85) call bpf_seq_printf#126
R1_w=ptr_seq_file(id=0,off=0,imm=0) R2_w=map_value(id=0,off=0,ks=4,vs=4,imm=0)
R3_w=inv4 R4_w=fp-8 R5_w=inv8 R10=fp0 fp-8_w=map_value
last_idx 11 first_idx 0
regs=8 stack=0 before 10: (b4) w5 = 8
regs=8 stack=0 before 9: (b4) w3 = 4
invalid indirect read from stack off -8+0 size 8
Basically, the verifier complains the map_value pointer at "fp-8" location.
To fix the issue, if env->allow_ptr_leaks is true, let us also permit
pointers on the stack to be accessible by the helper.
Suggested-by: Alexei Starovoitov <ast@kernel.org>
Reported-by: Song Liu <songliubraving@fb.com>
Signed-off-by: Yonghong Song <yhs@fb.com>
---
kernel/bpf/verifier.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 93def76cf32b..9159c9822ede 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -3769,7 +3769,8 @@ static int check_stack_boundary(struct bpf_verifier_env *env, int regno,
goto mark;
if (state->stack[spi].slot_type[0] == STACK_SPILL &&
- state->stack[spi].spilled_ptr.type == SCALAR_VALUE) {
+ (state->stack[spi].spilled_ptr.type == SCALAR_VALUE ||
+ env->allow_ptr_leaks)) {
__mark_reg_unknown(env, &state->stack[spi].spilled_ptr);
for (j = 0; j < BPF_REG_SIZE; j++)
state->stack[spi].slot_type[j] = STACK_MISC;
--
2.24.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH bpf-next v2 2/2] selftests/bpf: add a test for ptr_to_map_value on stack for helper access
2020-12-10 1:33 [PATCH bpf-next v2 0/2] bpf: permits pointers on stack for helper calls Yonghong Song
2020-12-10 1:33 ` [PATCH bpf-next v2 1/2] " Yonghong Song
@ 2020-12-10 1:33 ` Yonghong Song
2020-12-10 17:19 ` Song Liu
1 sibling, 1 reply; 7+ messages in thread
From: Yonghong Song @ 2020-12-10 1:33 UTC (permalink / raw)
To: bpf; +Cc: Alexei Starovoitov, Daniel Borkmann, kernel-team
Change bpf_iter_task.c such that pointer to map_value may appear
on the stack for bpf_seq_printf() to access. Without previous
verifier patch, the bpf_iter test will fail.
Signed-off-by: Yonghong Song <yhs@fb.com>
---
tools/testing/selftests/bpf/progs/bpf_iter_task.c | 3 ++-
tools/testing/selftests/bpf/verifier/unpriv.c | 5 +++--
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/bpf/progs/bpf_iter_task.c b/tools/testing/selftests/bpf/progs/bpf_iter_task.c
index 4983087852a0..b7f32c160f4e 100644
--- a/tools/testing/selftests/bpf/progs/bpf_iter_task.c
+++ b/tools/testing/selftests/bpf/progs/bpf_iter_task.c
@@ -11,9 +11,10 @@ int dump_task(struct bpf_iter__task *ctx)
{
struct seq_file *seq = ctx->meta->seq;
struct task_struct *task = ctx->task;
+ static char info[] = " === END ===";
if (task == (void *)0) {
- BPF_SEQ_PRINTF(seq, " === END ===\n");
+ BPF_SEQ_PRINTF(seq, "%s\n", info);
return 0;
}
diff --git a/tools/testing/selftests/bpf/verifier/unpriv.c b/tools/testing/selftests/bpf/verifier/unpriv.c
index 91bb77c24a2e..a3fe0fbaed41 100644
--- a/tools/testing/selftests/bpf/verifier/unpriv.c
+++ b/tools/testing/selftests/bpf/verifier/unpriv.c
@@ -108,8 +108,9 @@
BPF_EXIT_INSN(),
},
.fixup_map_hash_8b = { 3 },
- .errstr = "invalid indirect read from stack off -8+0 size 8",
- .result = REJECT,
+ .errstr_unpriv = "invalid indirect read from stack off -8+0 size 8",
+ .result_unpriv = REJECT,
+ .result = ACCEPT,
},
{
"unpriv: mangle pointer on stack 1",
--
2.24.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH bpf-next v2 1/2] bpf: permits pointers on stack for helper calls
2020-12-10 1:33 ` [PATCH bpf-next v2 1/2] " Yonghong Song
@ 2020-12-10 17:18 ` Song Liu
2020-12-11 0:10 ` Daniel Borkmann
1 sibling, 0 replies; 7+ messages in thread
From: Song Liu @ 2020-12-10 17:18 UTC (permalink / raw)
To: Yonghong Song; +Cc: bpf, Alexei Starovoitov, Daniel Borkmann, Kernel Team
> On Dec 9, 2020, at 5:33 PM, Yonghong Song <yhs@fb.com> wrote:
>
> Currently, when checking stack memory accessed by helper calls,
> for spills, only PTR_TO_BTF_ID and SCALAR_VALUE are
> allowed.
>
> Song discovered an issue where the below bpf program
> int dump_task(struct bpf_iter__task *ctx)
> {
> struct seq_file *seq = ctx->meta->seq;
> static char[] info = "abc";
> BPF_SEQ_PRINTF(seq, "%s\n", info);
> return 0;
> }
> may cause a verifier failure.
>
> The verifier output looks like:
> ; struct seq_file *seq = ctx->meta->seq;
> 1: (79) r1 = *(u64 *)(r1 +0)
> ; BPF_SEQ_PRINTF(seq, "%s\n", info);
> 2: (18) r2 = 0xffff9054400f6000
> 4: (7b) *(u64 *)(r10 -8) = r2
> 5: (bf) r4 = r10
> ;
> 6: (07) r4 += -8
> ; BPF_SEQ_PRINTF(seq, "%s\n", info);
> 7: (18) r2 = 0xffff9054400fe000
> 9: (b4) w3 = 4
> 10: (b4) w5 = 8
> 11: (85) call bpf_seq_printf#126
> R1_w=ptr_seq_file(id=0,off=0,imm=0) R2_w=map_value(id=0,off=0,ks=4,vs=4,imm=0)
> R3_w=inv4 R4_w=fp-8 R5_w=inv8 R10=fp0 fp-8_w=map_value
> last_idx 11 first_idx 0
> regs=8 stack=0 before 10: (b4) w5 = 8
> regs=8 stack=0 before 9: (b4) w3 = 4
> invalid indirect read from stack off -8+0 size 8
>
> Basically, the verifier complains the map_value pointer at "fp-8" location.
> To fix the issue, if env->allow_ptr_leaks is true, let us also permit
> pointers on the stack to be accessible by the helper.
>
> Suggested-by: Alexei Starovoitov <ast@kernel.org>
> Reported-by: Song Liu <songliubraving@fb.com>
> Signed-off-by: Yonghong Song <yhs@fb.com>
Acked-by: Song Liu <songliubraving@fb.com>
Thanks for the fix!
> ---
> kernel/bpf/verifier.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 93def76cf32b..9159c9822ede 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -3769,7 +3769,8 @@ static int check_stack_boundary(struct bpf_verifier_env *env, int regno,
> goto mark;
>
> if (state->stack[spi].slot_type[0] == STACK_SPILL &&
> - state->stack[spi].spilled_ptr.type == SCALAR_VALUE) {
> + (state->stack[spi].spilled_ptr.type == SCALAR_VALUE ||
> + env->allow_ptr_leaks)) {
> __mark_reg_unknown(env, &state->stack[spi].spilled_ptr);
> for (j = 0; j < BPF_REG_SIZE; j++)
> state->stack[spi].slot_type[j] = STACK_MISC;
> --
> 2.24.1
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH bpf-next v2 2/2] selftests/bpf: add a test for ptr_to_map_value on stack for helper access
2020-12-10 1:33 ` [PATCH bpf-next v2 2/2] selftests/bpf: add a test for ptr_to_map_value on stack for helper access Yonghong Song
@ 2020-12-10 17:19 ` Song Liu
0 siblings, 0 replies; 7+ messages in thread
From: Song Liu @ 2020-12-10 17:19 UTC (permalink / raw)
To: Yonghong Song; +Cc: bpf, Alexei Starovoitov, Daniel Borkmann, Kernel Team
> On Dec 9, 2020, at 5:33 PM, Yonghong Song <yhs@fb.com> wrote:
>
> Change bpf_iter_task.c such that pointer to map_value may appear
> on the stack for bpf_seq_printf() to access. Without previous
> verifier patch, the bpf_iter test will fail.
>
> Signed-off-by: Yonghong Song <yhs@fb.com>
Acked-by: Song Liu <songliubraving@fb.com>
> ---
> tools/testing/selftests/bpf/progs/bpf_iter_task.c | 3 ++-
> tools/testing/selftests/bpf/verifier/unpriv.c | 5 +++--
> 2 files changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/tools/testing/selftests/bpf/progs/bpf_iter_task.c b/tools/testing/selftests/bpf/progs/bpf_iter_task.c
> index 4983087852a0..b7f32c160f4e 100644
> --- a/tools/testing/selftests/bpf/progs/bpf_iter_task.c
> +++ b/tools/testing/selftests/bpf/progs/bpf_iter_task.c
> @@ -11,9 +11,10 @@ int dump_task(struct bpf_iter__task *ctx)
> {
> struct seq_file *seq = ctx->meta->seq;
> struct task_struct *task = ctx->task;
> + static char info[] = " === END ===";
>
> if (task == (void *)0) {
> - BPF_SEQ_PRINTF(seq, " === END ===\n");
> + BPF_SEQ_PRINTF(seq, "%s\n", info);
> return 0;
> }
>
> diff --git a/tools/testing/selftests/bpf/verifier/unpriv.c b/tools/testing/selftests/bpf/verifier/unpriv.c
> index 91bb77c24a2e..a3fe0fbaed41 100644
> --- a/tools/testing/selftests/bpf/verifier/unpriv.c
> +++ b/tools/testing/selftests/bpf/verifier/unpriv.c
> @@ -108,8 +108,9 @@
> BPF_EXIT_INSN(),
> },
> .fixup_map_hash_8b = { 3 },
> - .errstr = "invalid indirect read from stack off -8+0 size 8",
> - .result = REJECT,
> + .errstr_unpriv = "invalid indirect read from stack off -8+0 size 8",
> + .result_unpriv = REJECT,
> + .result = ACCEPT,
> },
> {
> "unpriv: mangle pointer on stack 1",
> --
> 2.24.1
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH bpf-next v2 1/2] bpf: permits pointers on stack for helper calls
2020-12-10 1:33 ` [PATCH bpf-next v2 1/2] " Yonghong Song
2020-12-10 17:18 ` Song Liu
@ 2020-12-11 0:10 ` Daniel Borkmann
2020-12-11 2:24 ` Yonghong Song
1 sibling, 1 reply; 7+ messages in thread
From: Daniel Borkmann @ 2020-12-11 0:10 UTC (permalink / raw)
To: Yonghong Song, bpf; +Cc: Alexei Starovoitov, kernel-team, Song Liu
On 12/10/20 2:33 AM, Yonghong Song wrote:
> Currently, when checking stack memory accessed by helper calls,
> for spills, only PTR_TO_BTF_ID and SCALAR_VALUE are
> allowed.
>
> Song discovered an issue where the below bpf program
> int dump_task(struct bpf_iter__task *ctx)
> {
> struct seq_file *seq = ctx->meta->seq;
> static char[] info = "abc";
> BPF_SEQ_PRINTF(seq, "%s\n", info);
> return 0;
> }
> may cause a verifier failure.
>
> The verifier output looks like:
> ; struct seq_file *seq = ctx->meta->seq;
> 1: (79) r1 = *(u64 *)(r1 +0)
> ; BPF_SEQ_PRINTF(seq, "%s\n", info);
> 2: (18) r2 = 0xffff9054400f6000
> 4: (7b) *(u64 *)(r10 -8) = r2
> 5: (bf) r4 = r10
> ;
> 6: (07) r4 += -8
> ; BPF_SEQ_PRINTF(seq, "%s\n", info);
> 7: (18) r2 = 0xffff9054400fe000
> 9: (b4) w3 = 4
> 10: (b4) w5 = 8
> 11: (85) call bpf_seq_printf#126
> R1_w=ptr_seq_file(id=0,off=0,imm=0) R2_w=map_value(id=0,off=0,ks=4,vs=4,imm=0)
> R3_w=inv4 R4_w=fp-8 R5_w=inv8 R10=fp0 fp-8_w=map_value
> last_idx 11 first_idx 0
> regs=8 stack=0 before 10: (b4) w5 = 8
> regs=8 stack=0 before 9: (b4) w3 = 4
> invalid indirect read from stack off -8+0 size 8
>
> Basically, the verifier complains the map_value pointer at "fp-8" location.
> To fix the issue, if env->allow_ptr_leaks is true, let us also permit
> pointers on the stack to be accessible by the helper.
>
> Suggested-by: Alexei Starovoitov <ast@kernel.org>
> Reported-by: Song Liu <songliubraving@fb.com>
> Signed-off-by: Yonghong Song <yhs@fb.com>
> ---
> kernel/bpf/verifier.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 93def76cf32b..9159c9822ede 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -3769,7 +3769,8 @@ static int check_stack_boundary(struct bpf_verifier_env *env, int regno,
> goto mark;
>
> if (state->stack[spi].slot_type[0] == STACK_SPILL &&
> - state->stack[spi].spilled_ptr.type == SCALAR_VALUE) {
> + (state->stack[spi].spilled_ptr.type == SCALAR_VALUE ||
> + env->allow_ptr_leaks)) {
Afaik, in check_stack_write() we mark some of the spilled_ptr.type as NOT_INIT,
shouldn't we at least avoid an implicit transition of NOT_INIT into SCALAR_VALUE?
> __mark_reg_unknown(env, &state->stack[spi].spilled_ptr);
> for (j = 0; j < BPF_REG_SIZE; j++)
> state->stack[spi].slot_type[j] = STACK_MISC;
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH bpf-next v2 1/2] bpf: permits pointers on stack for helper calls
2020-12-11 0:10 ` Daniel Borkmann
@ 2020-12-11 2:24 ` Yonghong Song
0 siblings, 0 replies; 7+ messages in thread
From: Yonghong Song @ 2020-12-11 2:24 UTC (permalink / raw)
To: Daniel Borkmann, bpf; +Cc: Alexei Starovoitov, kernel-team, Song Liu
On 12/10/20 4:10 PM, Daniel Borkmann wrote:
> On 12/10/20 2:33 AM, Yonghong Song wrote:
>> Currently, when checking stack memory accessed by helper calls,
>> for spills, only PTR_TO_BTF_ID and SCALAR_VALUE are
>> allowed.
>>
>> Song discovered an issue where the below bpf program
>> int dump_task(struct bpf_iter__task *ctx)
>> {
>> struct seq_file *seq = ctx->meta->seq;
>> static char[] info = "abc";
>> BPF_SEQ_PRINTF(seq, "%s\n", info);
>> return 0;
>> }
>> may cause a verifier failure.
>>
>> The verifier output looks like:
>> ; struct seq_file *seq = ctx->meta->seq;
>> 1: (79) r1 = *(u64 *)(r1 +0)
>> ; BPF_SEQ_PRINTF(seq, "%s\n", info);
>> 2: (18) r2 = 0xffff9054400f6000
>> 4: (7b) *(u64 *)(r10 -8) = r2
>> 5: (bf) r4 = r10
>> ;
>> 6: (07) r4 += -8
>> ; BPF_SEQ_PRINTF(seq, "%s\n", info);
>> 7: (18) r2 = 0xffff9054400fe000
>> 9: (b4) w3 = 4
>> 10: (b4) w5 = 8
>> 11: (85) call bpf_seq_printf#126
>> R1_w=ptr_seq_file(id=0,off=0,imm=0)
>> R2_w=map_value(id=0,off=0,ks=4,vs=4,imm=0)
>> R3_w=inv4 R4_w=fp-8 R5_w=inv8 R10=fp0 fp-8_w=map_value
>> last_idx 11 first_idx 0
>> regs=8 stack=0 before 10: (b4) w5 = 8
>> regs=8 stack=0 before 9: (b4) w3 = 4
>> invalid indirect read from stack off -8+0 size 8
>>
>> Basically, the verifier complains the map_value pointer at "fp-8"
>> location.
>> To fix the issue, if env->allow_ptr_leaks is true, let us also permit
>> pointers on the stack to be accessible by the helper.
>>
>> Suggested-by: Alexei Starovoitov <ast@kernel.org>
>> Reported-by: Song Liu <songliubraving@fb.com>
>> Signed-off-by: Yonghong Song <yhs@fb.com>
>> ---
>> kernel/bpf/verifier.c | 3 ++-
>> 1 file changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
>> index 93def76cf32b..9159c9822ede 100644
>> --- a/kernel/bpf/verifier.c
>> +++ b/kernel/bpf/verifier.c
>> @@ -3769,7 +3769,8 @@ static int check_stack_boundary(struct
>> bpf_verifier_env *env, int regno,
>> goto mark;
>> if (state->stack[spi].slot_type[0] == STACK_SPILL &&
>> - state->stack[spi].spilled_ptr.type == SCALAR_VALUE) {
>> + (state->stack[spi].spilled_ptr.type == SCALAR_VALUE ||
>> + env->allow_ptr_leaks)) {
>
> Afaik, in check_stack_write() we mark some of the spilled_ptr.type as
> NOT_INIT,
> shouldn't we at least avoid an implicit transition of NOT_INIT into
> SCALAR_VALUE?
Make sense! here we check env->allow_ptr_leaks and we should the
spilled_ptr.type for allow_ptr_leaks should be a pointer (!= NOT_INIT).
Will send v3 soon.
>
>> __mark_reg_unknown(env, &state->stack[spi].spilled_ptr);
>> for (j = 0; j < BPF_REG_SIZE; j++)
>> state->stack[spi].slot_type[j] = STACK_MISC;
>>
>
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2020-12-11 2:26 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-10 1:33 [PATCH bpf-next v2 0/2] bpf: permits pointers on stack for helper calls Yonghong Song
2020-12-10 1:33 ` [PATCH bpf-next v2 1/2] " Yonghong Song
2020-12-10 17:18 ` Song Liu
2020-12-11 0:10 ` Daniel Borkmann
2020-12-11 2:24 ` Yonghong Song
2020-12-10 1:33 ` [PATCH bpf-next v2 2/2] selftests/bpf: add a test for ptr_to_map_value on stack for helper access Yonghong Song
2020-12-10 17:19 ` Song Liu
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.