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>