🇰🇷 한글 설명
Linux 커널의 BPF 검증기(verifier)에서 포인터가 NULL이 아님을 잘못 추론하는 취약점이 발견되었습니다. 특정 조건에서 포인터 타입에 PTR_MAYBE_NULL 플래그가 없더라도 실제 런타임 시 NULL 값이 될 수 있어, 검증기가 NULL 포인터 역참조를 감지하지 못할 수 있습니다.
💡 쉬운 설명
컴퓨터가 '이 데이터는 비어있지 않다'라고 잘못 판단하여, 실제로는 비어있는 데이터를 사용하려다 시스템 오류를 일으킬 수 있는 문제입니다. 이로 인해 보안 검사를 우회하여 시스템에 문제를 일으킬 수 있습니다.
🇺🇸 원문 (English)
In the Linux kernel, the following vulnerability has been resolved:
bpf: check_cond_jmp_op(): properly infer if register is null
Nicholas Carlini reported a bug when verifier can incorrectly infer
that a pointer is non-null. The bug occurs when two pointers are
compared and one of them has a type w/o PTR_MAYBE_NULL flag,
but which allows a value to be NULL at runtime.
Here is an example:
// `a` is PTR_TO_MEM | MEM_RDONLY | PTR_UNTRUSTED
// `a` is 0 at runtime.
// `b` is PTR_TO_MAP_VALUE | PTR_MAYBE_NULL
void *a = bpf_rdonly_cast(0, 0);
int *b = bpf_map_lookup_elem(...);
if (a == b)
*b = 42; // verifier does not catch null pointer dereference
This happens because of a special case in check_cond_jmp_op(),
which attempts to strip PTR_MAYBE_NULL flags from pointer types,
when processing comparisons like `rA == rB`, if either rA or rB can't
be null.
The non-null property is derived based on the absence of
PTR_MAYBE_NULL flag on rA's or rB's type. But that is not sufficient
for types like PTR_TO_MEM, as in the example.
This patch replaces type_may_be_null() call with reg_not_null(),
which contains an allowlist of types for which absence of
PTR_MAYBE_NULL actually means that the value can't be NULL at runtime.
At the moment, the list in the reg_not_null() omits two types for
which PTR_MAYBE_NULL is applicable: PTR_TO_XDP_SOCK and PTR_TO_BUF.
In order to remain backward compatible, and assuming that only
comparison between pointers of the same type makes sense,
this commit extends reg_not_null(). W/o such an extension e.g.
verifier_jeq_infer_not_null/null_ptr_to_map_value fails.
reg_not_null() can be extended further, but I deem that out of scope
for the fix at hand. Explicit base_type(...) != PTR_TO_BTF_ID
checks in the check_cond_jmp_op() can be removed with migration to
reg_not_null(), but that is a behavioural change, as the special case
would start matching for PTR_TO_BTF_ID that is also is_trusted_reg().
I omit the behavioural change from this commit.
📍 영향받는 시스템
Linux Kernel (BPF verifier 관련 버전)
⚔️ 공격 벡터
조작된 BPF 프로그램을 로드하여 검증기의 포인터 추론 로직을 우회하고 NULL 포인터 역참조 유도
🛡️ 대응 방법
해당 취약점이 수정된 최신 Linux 커널 버전으로 업데이트
🔧 검증 코드
출력된 커널 버전이 해당 취약점이 패치된 버전인지 배포판 보안 공지를 통해 확인