CVE-2022-49961

Severity CVSS v4.0:
Pending analysis
Type:
CWE-125 Out-of-bounds Read
Publication date:
18/06/2025
Last modified:
14/11/2025

Description

In the Linux kernel, the following vulnerability has been resolved:<br /> <br /> bpf: Do mark_chain_precision for ARG_CONST_ALLOC_SIZE_OR_ZERO<br /> <br /> Precision markers need to be propagated whenever we have an ARG_CONST_*<br /> style argument, as the verifier cannot consider imprecise scalars to be<br /> equivalent for the purposes of states_equal check when such arguments<br /> refine the return value (in this case, set mem_size for PTR_TO_MEM). The<br /> resultant mem_size for the R0 is derived from the constant value, and if<br /> the verifier incorrectly prunes states considering them equivalent where<br /> such arguments exist (by seeing that both registers have reg-&gt;precise as<br /> false in regsafe), we can end up with invalid programs passing the<br /> verifier which can do access beyond what should have been the correct<br /> mem_size in that explored state.<br /> <br /> To show a concrete example of the problem:<br /> <br /> 0000000000000000 :<br /> 0: r2 = *(u32 *)(r1 + 80)<br /> 1: r1 = *(u32 *)(r1 + 76)<br /> 2: r3 = r1<br /> 3: r3 += 4<br /> 4: if r3 &gt; r2 goto +18 <br /> 5: w2 = 0<br /> 6: *(u32 *)(r1 + 0) = r2<br /> 7: r1 = *(u32 *)(r1 + 0)<br /> 8: r2 = 1<br /> 9: if w1 == 0 goto +1 <br /> 10: r2 = -1<br /> <br /> 0000000000000058 :<br /> 11: r1 = 0 ll<br /> 13: r3 = 0<br /> 14: call bpf_ringbuf_reserve<br /> 15: if r0 == 0 goto +7 <br /> 16: r1 = r0<br /> 17: r1 += 16777215<br /> 18: w2 = 0<br /> 19: *(u8 *)(r1 + 0) = r2<br /> 20: r1 = r0<br /> 21: r2 = 0<br /> 22: call bpf_ringbuf_submit<br /> <br /> 00000000000000b8 :<br /> 23: w0 = 0<br /> 24: exit<br /> <br /> For the first case, the single line execution&amp;#39;s exploration will prune<br /> the search at insn 14 for the branch insn 9&amp;#39;s second leg as it will be<br /> verified first using r2 = -1 (UINT_MAX), while as w1 at insn 9 will<br /> always be 0 so at runtime we don&amp;#39;t get error for being greater than<br /> UINT_MAX/4 from bpf_ringbuf_reserve. The verifier during regsafe just<br /> sees reg-&gt;precise as false for both r2 registers in both states, hence<br /> considers them equal for purposes of states_equal.<br /> <br /> If we propagated precise markers using the backtracking support, we<br /> would use the precise marking to then ensure that old r2 (UINT_MAX) was<br /> within the new r2 (1) and this would never be true, so the verification<br /> would rightfully fail.<br /> <br /> The end result is that the out of bounds access at instruction 19 would<br /> be permitted without this fix.<br /> <br /> Note that reg-&gt;precise is always set to true when user does not have<br /> CAP_BPF (or when subprog count is greater than 1 (i.e. use of any static<br /> or global functions)), hence this is only a problem when precision marks<br /> need to be explicitly propagated (i.e. privileged users with CAP_BPF).<br /> <br /> A simplified test case has been included in the next patch to prevent<br /> future regressions.

Vulnerable products and versions

CPE From Up to
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 5.8 (including) 5.19.8 (excluding)
cpe:2.3:o:linux:linux_kernel:6.0:rc1:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.0:rc2:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.0:rc3:*:*:*:*:*:*