🇰🇷 한글 설명
Linux 커널 BPF 검증기에서 초기화되지 않은 스택 슬롯에 대한 접근이 일관되지 않게 처리되던 문제를 수정했습니다. 특권 프로그램의 미초기화 스택 읽기 허용 조건이 스택 크기에 따라 달라졌고, 가변 오프셋 쓰기 시 스택 크기 추적이 잘못되어 런타임에 범위를 벗어난 데이터를 읽을 수 있었습니다.
💡 쉬운 설명
리눅스 커널 안의 eBPF 검사 기능이 메모리 사용량을 제대로 계산하지 못하는 결함이 있었습니다. 이로 인해 악의적인 프로그램이 허용되지 않은 메모리 영역의 데이터를 읽을 수 있었습니다.
🇺🇸 원문 (English)
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.
📍 영향받는 시스템
Linux 커널 (eBPF 기능을 포함한 수정 이전 버전)
⚔️ 공격 벡터
eBPF 프로그램을 로드할 수 있는 권한을 가진 로컬 사용자가 가변 오프셋 스택 접근을 이용해 범위를 벗어난 커널 메모리를 읽음
🛡️ 대응 방법
Linux 커널을 해당 CVE 수정이 포함된 최신 버전으로 업데이트하고 재부팅
🔧 검증 코드
출력된 커널 버전을 배포판 보안 공지에서 CVE-2023-52452 수정이 포함된 버전과 비교하여, 같거나 높으면 패치된 것으로 판단