CVE-2022-49658

bpf: Fix insufficient bounds propagation from adjust_scalar_min_max_vals

published February 26, 2025

CVSS
—
EPSS
0%
Percentile
19.5
In the wild
Unconfirmed
What it is

In the Linux kernel, the following vulnerability has been resolved:

bpf: Fix insufficient bounds propagation from adjust_scalar_min_max_vals

Kuee reported a corner case where the tnum becomes constant after the call

to __reg_bound_offset(), but the register's bounds are not, that is, its

min bounds are still not equal to the register's max bounds.

This in turn allows to leak pointers through turning a pointer register as

is into an unknown scalar via adjust_ptr_min_max_vals().

Before:

func#0 @0

0: R1=ctx(off=0,imm=0,umax=0,var_off=(0x0; 0x0)) R10=fp(off=0,imm=0,umax=0,var_off=(0x0; 0x0))

0: (b7) r0 = 1 ; R0_w=scalar(imm=1,umin=1,umax=1,var_off=(0x1; 0x0))

1: (b7) r3 = 0 ; R3_w=scalar(imm=0,umax=0,var_off=(0x0; 0x0))

2: (87) r3 = -r3 ; R3_w=scalar()

3: (87) r3 = -r3 ; R3_w=scalar()

4: (47) r3 |= 32767 ; R3_w=scalar(smin=-9223372036854743041,umin=32767,var_off=(0x7fff; 0xffffffffffff8000),s32_min=-2147450881)

5: (75) if r3 s>= 0x0 goto pc+1 ; R3_w=scalar(umin=9223372036854808575,var_off=(0x8000000000007fff; 0x7fffffffffff8000),s32_min=-2147450881,u32_min=32767)

6: (95) exit

from 5 to 7: R0=scalar(imm=1,umin=1,umax=1,var_off=(0x1; 0x0)) R1=ctx(off=0,imm=0,umax=0,var_off=(0x0; 0x0)) R3=scalar(umin=32767,umax=9223372036854775807,var_off=(0x7fff; 0x7fffffffffff8000),s32_min=-2147450881) R10=fp(off=0,imm=0,umax=0,var_off=(0x0; 0x0))

7: (d5) if r3 s<= 0x8000 goto pc+1 ; R3=scalar(umin=32769,umax=9223372036854775807,var_off=(0x7fff; 0x7fffffffffff8000),s32_min=-2147450881,u32_min=32767)

8: (95) exit

from 7 to 9: R0=scalar(imm=1,umin=1,umax=1,var_off=(0x1; 0x0)) R1=ctx(off=0,imm=0,umax=0,var_off=(0x0; 0x0)) R3=scalar(umin=32767,umax=32768,var_off=(0x7fff; 0x8000)) R10=fp(off=0,imm=0,umax=0,var_off=(0x0; 0x0))

9: (07) r3 += -32767 ; R3_w=scalar(imm=0,umax=1,var_off=(0x0; 0x0)) <--- [*]

10: (95) exit

What can be seen here is that R3=scalar(umin=32767,umax=32768,var_off=(0x7fff;

0x8000)) after the operation R3 += -32767 results in a 'malformed' constant, that

is, R3_w=scalar(imm=0,umax=1,var_off=(0x0; 0x0)). Intersecting with var_off has

not been done at that point via __update_reg_bounds(), which would have improved

the umax to be equal to umin.

Refactor the tnum <> min/max bounds information flow into a reg_bounds_sync()

helper and use it consistently everywhere. After the fix, bounds have been

corrected to R3_w=scalar(imm=0,umax=0,var_off=(0x0; 0x0)) and thus the register

is regarded as a 'proper' constant scalar of 0.

After:

func#0 @0

0: R1=ctx(off=0,imm=0,umax=0,var_off=(0x0; 0x0)) R10=fp(off=0,imm=0,umax=0,var_off=(0x0; 0x0))

0: (b7) r0 = 1 ; R0_w=scalar(imm=1,umin=1,umax=1,var_off=(0x1; 0x0))

1: (b7) r3 = 0 ; R3_w=scalar(imm=0,umax=0,var_off=(0x0; 0x0))

2: (87) r3 = -r3 ; R3_w=scalar()

3: (87) r3 = -r3 ; R3_w=scalar()

4: (47) r3 |= 32767 ; R3_w=scalar(smin=-9223372036854743041,umin=32767,var_off=(0x7fff; 0xffffffffffff8000),s32_min=-2147450881)

5: (75) if r3 s>= 0x0 goto pc+1 ; R3_w=scalar(umin=9223372036854808575,var_off=(0x8000000000007fff; 0x7fffffffffff8000),s32_min=-2147450881,u32_min=32767)

6: (95) exit

from 5 to 7: R0=scalar(imm=1,umin=1,umax=1,var_off=(0x1; 0x0)) R1=ctx(off=0,imm=0,umax=0,var_off=(0x0; 0x0)) R3=scalar(umin=32767,umax=9223372036854775807,var_off=(0x7fff; 0x7fffffffffff8000),s32_min=-2147450881) R10=fp(off=0,imm=0,umax=0,var_off=(0x0; 0x0))

7: (d5) if r3 s<= 0x8000 goto pc+1 ; R3=scalar(umin=32769,umax=9223372036854775807,var_off=(0x7fff; 0x7fffffffffff8000),s32_min=-2147450881,u32_min=32767)

8: (95) exit

from 7 to 9: R0=scalar(imm=1,umin=1,umax=1,var_off=(0x1; 0x0)) R1=ctx(off=0,imm=0,umax=0,var_off=(0x0; 0x0)) R3=scalar(umin=32767,umax=32768,var_off=(0x7fff; 0x8000)) R10=fp(off=0

---truncated---

The record
Technical detail
CVSS
Not scored
CVSS v4.0
Not supplied
EPSS
0.00281 · 19.5th percentile
Published
2025-02-26T02:23Z
EPSS history
Timeline
  • 26 FEB 02:23Z
    bpf: Fix insufficient bounds propagation from adjust_scalar_min_max_vals
    cvelistv5