* Re: [PATCH for 4.1,4.4] bpf: fix incorrect sign extension in check_alu_op()
2018-03-19 16:55 ` [PATCH for 4.1,4.4] bpf: fix incorrect sign extension in check_alu_op() Jann Horn
@ 2018-03-19 16:58 ` Daniel Borkmann
2018-03-19 17:13 ` Patch "bpf: fix incorrect sign extension in check_alu_op()" has been added to the 4.4-stable tree gregkh
2018-03-19 17:13 ` [PATCH for 4.1,4.4] bpf: fix incorrect sign extension in check_alu_op() Greg Kroah-Hartman
2 siblings, 0 replies; 6+ messages in thread
From: Daniel Borkmann @ 2018-03-19 16:58 UTC (permalink / raw)
To: Jann Horn, stable
Cc: security, David S. Miller, Alexei Starovoitov, Greg Kroah-Hartman
On 03/19/2018 05:55 PM, Jann Horn wrote:
> commit 95a762e2c8c942780948091f8f2a4f32fce1ac6f upstream.
>
> Distinguish between
> BPF_ALU64|BPF_MOV|BPF_K (load 32-bit immediate, sign-extended to 64-bit)
> and BPF_ALU|BPF_MOV|BPF_K (load 32-bit immediate, zero-padded to 64-bit);
> only perform sign extension in the first case.
>
> This patch differs from the mainline one because the verifier's internals
> have changed in the meantime. Mainline tracks register values as 64-bit
> values; however, 4.4 still stores tracked register values as 32-bit
> values with sign extension. Therefore, in the case of a 32-bit op with
> negative immediate, the value can't be tracked; leave the register as
> UNKNOWN_VALUE (set by the preceding check_reg_arg() call).
>
>
> I have manually tested this patch on top of 4.4.122. For the following BPF
> bytecode:
>
> BPF_MOV64_IMM(BPF_REG_1, 1),
> BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 1),
> BPF_EXIT_INSN(),
>
> BPF_MOV32_IMM(BPF_REG_1, 1),
> BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 1),
> BPF_EXIT_INSN(),
>
> BPF_MOV64_IMM(BPF_REG_1, -1),
> BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, -1, 1),
> BPF_EXIT_INSN(),
>
> BPF_MOV32_IMM(BPF_REG_1, -1),
> BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, -1, 2),
> BPF_MOV32_IMM(BPF_REG_0, 42),
> BPF_EXIT_INSN(),
>
> BPF_MOV32_IMM(BPF_REG_0, 43),
> BPF_EXIT_INSN()
>
> Verifier output on 4.4.122 without this patch:
>
> 0: (b7) r1 = 1
> 1: (15) if r1 == 0x1 goto pc+1
> 3: (b4) (u32) r1 = (u32) 1
> 4: (15) if r1 == 0x1 goto pc+1
> 6: (b7) r1 = -1
> 7: (15) if r1 == 0xffffffff goto pc+1
> 9: (b4) (u32) r1 = (u32) -1
> 10: (15) if r1 == 0xffffffff goto pc+2
> 13: (b4) (u32) r0 = (u32) 43
> 14: (95) exit
>
> Verifier output on 4.4.122+ with this patch:
>
> 0: (b7) r1 = 1
> 1: (15) if r1 == 0x1 goto pc+1
> 3: (b4) (u32) r1 = (u32) 1
> 4: (15) if r1 == 0x1 goto pc+1
> 6: (b7) r1 = -1
> 7: (15) if r1 == 0xffffffff goto pc+1
> 9: (b4) (u32) r1 = (u32) -1
> 10: (15) if r1 == 0xffffffff goto pc+2
> R1=inv R10=fp
> 11: (b4) (u32) r0 = (u32) 42
> 12: (95) exit
>
> from 10 to 13: R1=imm-1 R10=fp
> 13: (b4) (u32) r0 = (u32) 43
> 14: (95) exit
>
>
> This patch should be applied to linux-4.4.y and linux-4.1.y.
>
> Signed-off-by: Jann Horn <jannh@google.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Looks good, thanks Jann!
^ permalink raw reply [flat|nested] 6+ messages in thread
* Patch "bpf: fix incorrect sign extension in check_alu_op()" has been added to the 4.4-stable tree
2018-03-19 16:55 ` [PATCH for 4.1,4.4] bpf: fix incorrect sign extension in check_alu_op() Jann Horn
2018-03-19 16:58 ` Daniel Borkmann
@ 2018-03-19 17:13 ` gregkh
2018-03-19 17:13 ` [PATCH for 4.1,4.4] bpf: fix incorrect sign extension in check_alu_op() Greg Kroah-Hartman
2 siblings, 0 replies; 6+ messages in thread
From: gregkh @ 2018-03-19 17:13 UTC (permalink / raw)
To: jannh, ast, daniel, davem, gregkh; +Cc: stable, stable-commits
This is a note to let you know that I've just added the patch titled
bpf: fix incorrect sign extension in check_alu_op()
to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
bpf-fix-incorrect-sign-extension-in-check_alu_op.patch
and it can be found in the queue-4.4 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@vger.kernel.org> know about it.
>From jannh@google.com Mon Mar 19 18:11:54 2018
From: Jann Horn <jannh@google.com>
Date: Mon, 19 Mar 2018 17:55:52 +0100
Subject: bpf: fix incorrect sign extension in check_alu_op()
To: stable@vger.kernel.org
Cc: security@kernel.org, "David S. Miller" <davem@davemloft.net>, Daniel Borkmann <daniel@iogearbox.net>, Alexei Starovoitov <ast@kernel.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Message-ID: <20180319165552.146891-1-jannh@google.com>
From: Jann Horn <jannh@google.com>
commit 95a762e2c8c942780948091f8f2a4f32fce1ac6f upstream.
Distinguish between
BPF_ALU64|BPF_MOV|BPF_K (load 32-bit immediate, sign-extended to 64-bit)
and BPF_ALU|BPF_MOV|BPF_K (load 32-bit immediate, zero-padded to 64-bit);
only perform sign extension in the first case.
This patch differs from the mainline one because the verifier's internals
have changed in the meantime. Mainline tracks register values as 64-bit
values; however, 4.4 still stores tracked register values as 32-bit
values with sign extension. Therefore, in the case of a 32-bit op with
negative immediate, the value can't be tracked; leave the register as
UNKNOWN_VALUE (set by the preceding check_reg_arg() call).
I have manually tested this patch on top of 4.4.122. For the following BPF
bytecode:
BPF_MOV64_IMM(BPF_REG_1, 1),
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 1),
BPF_EXIT_INSN(),
BPF_MOV32_IMM(BPF_REG_1, 1),
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 1),
BPF_EXIT_INSN(),
BPF_MOV64_IMM(BPF_REG_1, -1),
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, -1, 1),
BPF_EXIT_INSN(),
BPF_MOV32_IMM(BPF_REG_1, -1),
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, -1, 2),
BPF_MOV32_IMM(BPF_REG_0, 42),
BPF_EXIT_INSN(),
BPF_MOV32_IMM(BPF_REG_0, 43),
BPF_EXIT_INSN()
Verifier output on 4.4.122 without this patch:
0: (b7) r1 = 1
1: (15) if r1 == 0x1 goto pc+1
3: (b4) (u32) r1 = (u32) 1
4: (15) if r1 == 0x1 goto pc+1
6: (b7) r1 = -1
7: (15) if r1 == 0xffffffff goto pc+1
9: (b4) (u32) r1 = (u32) -1
10: (15) if r1 == 0xffffffff goto pc+2
13: (b4) (u32) r0 = (u32) 43
14: (95) exit
Verifier output on 4.4.122+ with this patch:
0: (b7) r1 = 1
1: (15) if r1 == 0x1 goto pc+1
3: (b4) (u32) r1 = (u32) 1
4: (15) if r1 == 0x1 goto pc+1
6: (b7) r1 = -1
7: (15) if r1 == 0xffffffff goto pc+1
9: (b4) (u32) r1 = (u32) -1
10: (15) if r1 == 0xffffffff goto pc+2
R1=inv R10=fp
11: (b4) (u32) r0 = (u32) 42
12: (95) exit
from 10 to 13: R1=imm-1 R10=fp
13: (b4) (u32) r0 = (u32) 43
14: (95) exit
Signed-off-by: Jann Horn <jannh@google.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
kernel/bpf/verifier.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -1135,7 +1135,8 @@ static int check_alu_op(struct verifier_
regs[insn->dst_reg].type = UNKNOWN_VALUE;
regs[insn->dst_reg].map_ptr = NULL;
}
- } else {
+ } else if (BPF_CLASS(insn->code) == BPF_ALU64 ||
+ insn->imm >= 0) {
/* case: R = imm
* remember the value we stored into this reg
*/
Patches currently in stable-queue which might be from jannh@google.com are
queue-4.4/fs-aio-add-explicit-rcu-grace-period-when-freeing-kioctx.patch
queue-4.4/fs-aio-use-rcu-accessors-for-kioctx_table-table.patch
queue-4.4/bpf-fix-incorrect-sign-extension-in-check_alu_op.patch
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH for 4.1,4.4] bpf: fix incorrect sign extension in check_alu_op()
2018-03-19 16:55 ` [PATCH for 4.1,4.4] bpf: fix incorrect sign extension in check_alu_op() Jann Horn
2018-03-19 16:58 ` Daniel Borkmann
2018-03-19 17:13 ` Patch "bpf: fix incorrect sign extension in check_alu_op()" has been added to the 4.4-stable tree gregkh
@ 2018-03-19 17:13 ` Greg Kroah-Hartman
2 siblings, 0 replies; 6+ messages in thread
From: Greg Kroah-Hartman @ 2018-03-19 17:13 UTC (permalink / raw)
To: Jann Horn
Cc: stable, security, David S. Miller, Daniel Borkmann,
Alexei Starovoitov
On Mon, Mar 19, 2018 at 05:55:52PM +0100, Jann Horn wrote:
> commit 95a762e2c8c942780948091f8f2a4f32fce1ac6f upstream.
>
> Distinguish between
> BPF_ALU64|BPF_MOV|BPF_K (load 32-bit immediate, sign-extended to 64-bit)
> and BPF_ALU|BPF_MOV|BPF_K (load 32-bit immediate, zero-padded to 64-bit);
> only perform sign extension in the first case.
>
> This patch differs from the mainline one because the verifier's internals
> have changed in the meantime. Mainline tracks register values as 64-bit
> values; however, 4.4 still stores tracked register values as 32-bit
> values with sign extension. Therefore, in the case of a 32-bit op with
> negative immediate, the value can't be tracked; leave the register as
> UNKNOWN_VALUE (set by the preceding check_reg_arg() call).
>
>
> I have manually tested this patch on top of 4.4.122. For the following BPF
> bytecode:
>
> BPF_MOV64_IMM(BPF_REG_1, 1),
> BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 1),
> BPF_EXIT_INSN(),
>
> BPF_MOV32_IMM(BPF_REG_1, 1),
> BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 1, 1),
> BPF_EXIT_INSN(),
>
> BPF_MOV64_IMM(BPF_REG_1, -1),
> BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, -1, 1),
> BPF_EXIT_INSN(),
>
> BPF_MOV32_IMM(BPF_REG_1, -1),
> BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, -1, 2),
> BPF_MOV32_IMM(BPF_REG_0, 42),
> BPF_EXIT_INSN(),
>
> BPF_MOV32_IMM(BPF_REG_0, 43),
> BPF_EXIT_INSN()
>
> Verifier output on 4.4.122 without this patch:
>
> 0: (b7) r1 = 1
> 1: (15) if r1 == 0x1 goto pc+1
> 3: (b4) (u32) r1 = (u32) 1
> 4: (15) if r1 == 0x1 goto pc+1
> 6: (b7) r1 = -1
> 7: (15) if r1 == 0xffffffff goto pc+1
> 9: (b4) (u32) r1 = (u32) -1
> 10: (15) if r1 == 0xffffffff goto pc+2
> 13: (b4) (u32) r0 = (u32) 43
> 14: (95) exit
>
> Verifier output on 4.4.122+ with this patch:
>
> 0: (b7) r1 = 1
> 1: (15) if r1 == 0x1 goto pc+1
> 3: (b4) (u32) r1 = (u32) 1
> 4: (15) if r1 == 0x1 goto pc+1
> 6: (b7) r1 = -1
> 7: (15) if r1 == 0xffffffff goto pc+1
> 9: (b4) (u32) r1 = (u32) -1
> 10: (15) if r1 == 0xffffffff goto pc+2
> R1=inv R10=fp
> 11: (b4) (u32) r0 = (u32) 42
> 12: (95) exit
>
> from 10 to 13: R1=imm-1 R10=fp
> 13: (b4) (u32) r0 = (u32) 43
> 14: (95) exit
>
>
> This patch should be applied to linux-4.4.y and linux-4.1.y.
Now queued up for 4.4.y, thanks!
greg k-h
^ permalink raw reply [flat|nested] 6+ messages in thread