* [PATCH bpf] bpf: Fix possible out of bound write in narrow load handling
@ 2021-08-18 22:11 Andrey Ignatov
2021-08-18 22:48 ` Daniel Borkmann
0 siblings, 1 reply; 3+ messages in thread
From: Andrey Ignatov @ 2021-08-18 22:11 UTC (permalink / raw)
To: bpf; +Cc: Andrey Ignatov, ast, daniel, andriin, dan.carpenter, kernel-team
Fix a verifier bug found by smatch static checker in [0].
When narrow load is handled, one or two new instructions are added to
insn_buf array, but before it was only checked that
cnt >= ARRAY_SIZE(insn_buf)
And it's safe to add a new instruction to insn_buf[cnt++] only once. The
second try will lead to out of bound write. And this is what can happen
if `shift` is set.
Fix it by making sure that if the BPF_RSH instruction has to be added in
addition to BPF_AND then there is enough space for two more instructions
in insn_buf.
The full report [0] is below:
kernel/bpf/verifier.c:12304 convert_ctx_accesses() warn: offset 'cnt' incremented past end of array
kernel/bpf/verifier.c:12311 convert_ctx_accesses() warn: offset 'cnt' incremented past end of array
kernel/bpf/verifier.c
12282
12283 insn->off = off & ~(size_default - 1);
12284 insn->code = BPF_LDX | BPF_MEM | size_code;
12285 }
12286
12287 target_size = 0;
12288 cnt = convert_ctx_access(type, insn, insn_buf, env->prog,
12289 &target_size);
12290 if (cnt == 0 || cnt >= ARRAY_SIZE(insn_buf) ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Bounds check.
12291 (ctx_field_size && !target_size)) {
12292 verbose(env, "bpf verifier is misconfigured\n");
12293 return -EINVAL;
12294 }
12295
12296 if (is_narrower_load && size < target_size) {
12297 u8 shift = bpf_ctx_narrow_access_offset(
12298 off, size, size_default) * 8;
12299 if (ctx_field_size <= 4) {
12300 if (shift)
12301 insn_buf[cnt++] = BPF_ALU32_IMM(BPF_RSH,
^^^^^
increment beyond end of array
12302 insn->dst_reg,
12303 shift);
--> 12304 insn_buf[cnt++] = BPF_ALU32_IMM(BPF_AND, insn->dst_reg,
^^^^^
out of bounds write
12305 (1 << size * 8) - 1);
12306 } else {
12307 if (shift)
12308 insn_buf[cnt++] = BPF_ALU64_IMM(BPF_RSH,
12309 insn->dst_reg,
12310 shift);
12311 insn_buf[cnt++] = BPF_ALU64_IMM(BPF_AND, insn->dst_reg,
^^^^^^^^^^^^^^^
Same.
12312 (1ULL << size * 8) - 1);
12313 }
12314 }
12315
12316 new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
12317 if (!new_prog)
12318 return -ENOMEM;
12319
12320 delta += cnt - 1;
12321
12322 /* keep walking new program and skip insns we just inserted */
12323 env->prog = new_prog;
12324 insn = new_prog->insnsi + i + delta;
12325 }
12326
12327 return 0;
12328 }
[0] https://lore.kernel.org/bpf/20210817050843.GA21456@kili/
Fixes: 46f53a65d2de ("bpf: Allow narrow loads with offset > 0")
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Andrey Ignatov <rdna@fb.com>
---
kernel/bpf/verifier.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 381d3d6f24bc..b991fb0a5da4 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -12004,6 +12004,10 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
if (is_narrower_load && size < target_size) {
u8 shift = bpf_ctx_narrow_access_offset(
off, size, size_default) * 8;
+ if (shift && cnt + 1 >= ARRAY_SIZE(insn_buf)) {
+ verbose(env, "bpf verifier narrow ctx load misconfigured\n");
+ return -EINVAL;
+ }
if (ctx_field_size <= 4) {
if (shift)
insn_buf[cnt++] = BPF_ALU32_IMM(BPF_RSH,
--
2.30.2
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH bpf] bpf: Fix possible out of bound write in narrow load handling
2021-08-18 22:11 [PATCH bpf] bpf: Fix possible out of bound write in narrow load handling Andrey Ignatov
@ 2021-08-18 22:48 ` Daniel Borkmann
2021-08-18 23:00 ` Andrey Ignatov
0 siblings, 1 reply; 3+ messages in thread
From: Daniel Borkmann @ 2021-08-18 22:48 UTC (permalink / raw)
To: Andrey Ignatov, bpf; +Cc: ast, andriin, dan.carpenter, kernel-team
On 8/19/21 12:11 AM, Andrey Ignatov wrote:
> Fix a verifier bug found by smatch static checker in [0].
>
> When narrow load is handled, one or two new instructions are added to
> insn_buf array, but before it was only checked that
>
> cnt >= ARRAY_SIZE(insn_buf)
>
> And it's safe to add a new instruction to insn_buf[cnt++] only once. The
> second try will lead to out of bound write. And this is what can happen
> if `shift` is set.
Afaik, the insn_buf[] should always be large enough, could you add something to
the commit message of this fix whether this created an actual issue in practice
where we do oob overrun insn_buf[] (or whether it's 'only' the static checker
report ... from above paragraph I read you saw the former in practice)?
Thanks,
Daniel
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH bpf] bpf: Fix possible out of bound write in narrow load handling
2021-08-18 22:48 ` Daniel Borkmann
@ 2021-08-18 23:00 ` Andrey Ignatov
0 siblings, 0 replies; 3+ messages in thread
From: Andrey Ignatov @ 2021-08-18 23:00 UTC (permalink / raw)
To: Daniel Borkmann; +Cc: bpf, ast, andriin, dan.carpenter, kernel-team
Daniel Borkmann <daniel@iogearbox.net> [Wed, 2021-08-18 15:48 -0700]:
> On 8/19/21 12:11 AM, Andrey Ignatov wrote:
> > Fix a verifier bug found by smatch static checker in [0].
> >
> > When narrow load is handled, one or two new instructions are added to
> > insn_buf array, but before it was only checked that
> >
> > cnt >= ARRAY_SIZE(insn_buf)
> >
> > And it's safe to add a new instruction to insn_buf[cnt++] only once. The
> > second try will lead to out of bound write. And this is what can happen
> > if `shift` is set.
>
> Afaik, the insn_buf[] should always be large enough, could you add something to
> the commit message of this fix whether this created an actual issue in practice
> where we do oob overrun insn_buf[] (or whether it's 'only' the static checker
> report ... from above paragraph I read you saw the former in practice)?
It's 'only' the static checker report. I've never seen this problem in
practice.
I also have an impression that convert_ctx_accesses should not in
general (or should never?) return too many insn to hit insn_buf[] limit,
but it may not be trivial to check all scenarios so I can't say for
sure. That's why it makes sense to me to address the report.
Sure, I can add this info to the commit message in v2.
--
Andrey Ignatov
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2021-08-18 23:01 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-18 22:11 [PATCH bpf] bpf: Fix possible out of bound write in narrow load handling Andrey Ignatov
2021-08-18 22:48 ` Daniel Borkmann
2021-08-18 23:00 ` Andrey Ignatov
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.