]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commit
UBUNTU: SAUCE: bpf: verifier: fix ALU32 bounds tracking with bitwise ops
authorThadeu Lima de Souza Cascardo <cascardo@canonical.com>
Wed, 28 Apr 2021 16:38:32 +0000 (13:38 -0300)
committerStefan Bader <stefan.bader@canonical.com>
Thu, 6 May 2021 15:26:21 +0000 (17:26 +0200)
commit23d4dade446324518b9c2102fc1c5099d6eb2f51
treedde70224dcc6a39ac793aace44b473905f3b4995
parentef84137a7c5439e8eb8a0ef651c48195eda63aee
UBUNTU: SAUCE: bpf: verifier: fix ALU32 bounds tracking with bitwise ops

When scalar32_min_max_* functions are called for AND, OR and XOR
operations, they assume the 64-bit function will handle the case where
the operands are known.

However, those functions only test for the lower 32 bits to be known
whereas scalar_min_max_* checks for the 64 bits.

In the cases where only the lower 32 bits are known, the ALU32 bounds
will not be properly updated, potentially leading to inconsistent
states.

Do not ignore the case where the lower 32 bits of the operands are
known. Update the ALU32 bounds even in those cases.

That has been tested both with cases where only the lower 32 bits are
known and when all bits are known. In the first case, bounds are
correctly tracked, and the latter case has no changes at all.

Before the fix:
17: R0=map_value(id=0,off=0,ks=4,vs=1024,imm=0) R1=invP(id=0,smin_value=-9223372036854775807,smax_value=9223372032559808513,umin_value=1,umax_value=18446744069414584321,var_off=(0x1; 0xffffffff00000000),s32_min_value=1,s32_max_value=1,u32_max_value=1) R2=invP(id=0,smin_value=-9223372036854775806,smax_value=9223372032559808514,umin_value=2,umax_value=18446744069414584322,var_off=(0x2; 0xffffffff00000000),s32_min_value=2,s32_max_value=2,u32_max_value=2) R10=fp0 fp-8=mmmmmmmm
17: (5f) r2 &= r1
18: R0=map_value(id=0,off=0,ks=4,vs=1024,imm=0) R1=invP(id=0,smin_value=-9223372036854775807,smax_value=9223372032559808513,umin_value=1,umax_value=18446744069414584321,var_off=(0x1; 0xffffffff00000000),s32_min_value=1,s32_max_value=1,u32_max_value=1) R2_w=invP(id=0,smax_value=9223372032559808512,umax_value=18446744069414584320,var_off=(0x0; 0xffffffff00000000),s32_min_value=2,s32_max_value=0,u32_min_value=2,u32_max_value=0) R10=fp0 fp-8=mmmmmmmm

After the fix:
17: R0=map_value(id=0,off=0,ks=4,vs=1024,imm=0) R1=invP(id=0,smin_value=-9223372036854775807,smax_value=9223372032559808513,umin_value=1,umax_value=18446744069414584321,var_off=(0x1; 0xffffffff00000000),s32_min_value=1,s32_max_value=1,u32_max_value=1) R2=invP(id=0,smin_value=-9223372036854775806,smax_value=9223372032559808514,umin_value=2,umax_value=18446744069414584322,var_off=(0x2; 0xffffffff00000000),s32_min_value=2,s32_max_value=2,u32_max_value=2) R10=fp0 fp-8=mmmmmmmm
17: (5f) r2 &= r1
18: R0=map_value(id=0,off=0,ks=4,vs=1024,imm=0) R1=invP(id=0,smin_value=-9223372036854775807,smax_value=9223372032559808513,umin_value=1,umax_value=18446744069414584321,var_off=(0x1; 0xffffffff00000000),s32_min_value=1,s32_max_value=1,u32_max_value=1) R2_w=invP(id=0,smax_value=9223372032559808512,umax_value=18446744069414584320,var_off=(0x0; 0xffffffff00000000),s32_min_value=0,s32_max_value=0,u32_max_value=0) R10=fp0 fp-8=mmmmmmmm

This fixes CVE-2021-3490, also known as ZDI-CAN-13590.

Reported-by: Manfred Paul (@_manfp)
Fixes: 3f50f132d840 ("bpf: Verifier, do explicit ALU32 bounds tracking")
Fixes: 2921c90d4718 ("bpf: Fix a verifier failure with xor")
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
Reviewed-by: Seth Arnold <seth.arnold@canonical.com>
CVE-2021-3490
Acked-by: Marcelo Henrique Cerri <marcelo.cerri@canonical.com>
Acked-by: Ian May <ian.may@canonical.com>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
kernel/bpf/verifier.c