| From bippy-5f407fcff5a0 Mon Sep 17 00:00:00 2001 |
| From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| To: <linux-cve-announce@vger.kernel.org> |
| Reply-to: <cve@kernel.org>, <linux-kernel@vger.kernel.org> |
| Subject: CVE-2023-52452: bpf: Fix accesses to uninit stack slots |
| |
| Description |
| =========== |
| |
| In the Linux kernel, the following vulnerability has been resolved: |
| |
| bpf: Fix accesses to uninit stack slots |
| |
| Privileged programs are supposed to be able to read uninitialized stack |
| memory (ever since 6715df8d5) but, before this patch, these accesses |
| were permitted inconsistently. In particular, accesses were permitted |
| above state->allocated_stack, but not below it. In other words, if the |
| stack was already "large enough", the access was permitted, but |
| otherwise the access was rejected instead of being allowed to "grow the |
| stack". This undesired rejection was happening in two places: |
| - in check_stack_slot_within_bounds() |
| - in check_stack_range_initialized() |
| This patch arranges for these accesses to be permitted. A bunch of tests |
| that were relying on the old rejection had to change; all of them were |
| changed to add also run unprivileged, in which case the old behavior |
| persists. One tests couldn't be updated - global_func16 - because it |
| can't run unprivileged for other reasons. |
| |
| This patch also fixes the tracking of the stack size for variable-offset |
| reads. This second fix is bundled in the same commit as the first one |
| because they're inter-related. Before this patch, writes to the stack |
| using registers containing a variable offset (as opposed to registers |
| with fixed, known values) were not properly contributing to the |
| function's needed stack size. As a result, it was possible for a program |
| to verify, but then to attempt to read out-of-bounds data at runtime |
| because a too small stack had been allocated for it. |
| |
| Each function tracks the size of the stack it needs in |
| bpf_subprog_info.stack_depth, which is maintained by |
| update_stack_depth(). For regular memory accesses, check_mem_access() |
| was calling update_state_depth() but it was passing in only the fixed |
| part of the offset register, ignoring the variable offset. This was |
| incorrect; the minimum possible value of that register should be used |
| instead. |
| |
| This tracking is now fixed by centralizing the tracking of stack size in |
| grow_stack_state(), and by lifting the calls to grow_stack_state() to |
| check_stack_access_within_bounds() as suggested by Andrii. The code is |
| now simpler and more convincingly tracks the correct maximum stack size. |
| check_stack_range_initialized() can now rely on enough stack having been |
| allocated for the access; this helps with the fix for the first issue. |
| |
| A few tests were changed to also check the stack depth computation. The |
| one that fails without this patch is verifier_var_off:stack_write_priv_vs_unpriv. |
| |
| The Linux kernel CVE team has assigned CVE-2023-52452 to this issue. |
| |
| |
| Affected and fixed versions |
| =========================== |
| |
| Issue introduced in 5.12 with commit 01f810ace9ed37255f27608a0864abebccf0aab3 and fixed in 6.6.14 with commit 0954982db8283016bf38e9db2da5adf47a102e19 |
| Issue introduced in 5.12 with commit 01f810ace9ed37255f27608a0864abebccf0aab3 and fixed in 6.7.2 with commit fbcf372c8eda2290470268e0afb5ab5d5f5d5fde |
| Issue introduced in 5.12 with commit 01f810ace9ed37255f27608a0864abebccf0aab3 and fixed in 6.8 with commit 6b4a64bafd107e521c01eec3453ce94a3fb38529 |
| Issue introduced in 5.10.33 with commit f3c4b01689d392373301e6e60d1b02c5b4020afc |
| Issue introduced in 5.11.17 with commit d1b725ea5d104caea250427899f4e2e3ab15b4fc |
| |
| Please see https://www.kernel.org for a full list of currently supported |
| kernel versions by the kernel community. |
| |
| Unaffected versions might change over time as fixes are backported to |
| older supported kernel versions. The official CVE entry at |
| https://cve.org/CVERecord/?id=CVE-2023-52452 |
| will be updated if fixes are backported, please check that for the most |
| up to date information about this issue. |
| |
| |
| Affected files |
| ============== |
| |
| The file(s) affected by this issue are: |
| kernel/bpf/verifier.c |
| tools/testing/selftests/bpf/progs/iters.c |
| tools/testing/selftests/bpf/progs/test_global_func16.c |
| tools/testing/selftests/bpf/progs/verifier_basic_stack.c |
| tools/testing/selftests/bpf/progs/verifier_int_ptr.c |
| tools/testing/selftests/bpf/progs/verifier_raw_stack.c |
| tools/testing/selftests/bpf/progs/verifier_var_off.c |
| tools/testing/selftests/bpf/verifier/atomic_cmpxchg.c |
| tools/testing/selftests/bpf/verifier/calls.c |
| |
| |
| Mitigation |
| ========== |
| |
| The Linux kernel CVE team recommends that you update to the latest |
| stable kernel version for this, and many other bugfixes. Individual |
| changes are never tested alone, but rather are part of a larger kernel |
| release. Cherry-picking individual commits is not recommended or |
| supported by the Linux kernel community at all. If however, updating to |
| the latest release is impossible, the individual changes to resolve this |
| issue can be found at these commits: |
| https://git.kernel.org/stable/c/0954982db8283016bf38e9db2da5adf47a102e19 |
| https://git.kernel.org/stable/c/fbcf372c8eda2290470268e0afb5ab5d5f5d5fde |
| https://git.kernel.org/stable/c/6b4a64bafd107e521c01eec3453ce94a3fb38529 |