🇰🇷 한글 설명
Linux 커널의 BPF 검증기(verifier)가 전역 함수 호출 시 패킷 데이터 변경 여부를 제대로 추적하지 못하는 취약점입니다. 이로 인해 특정 헬퍼 함수를 호출하는 전역 함수를 사용할 때, 검증기가 패킷 포인터의 유효성을 잘못 판단하여 메모리 안전성을 위협할 수 있습니다.
💡 쉬운 설명
프로그램이 실행 중에 데이터의 위치를 바꿀 수 있는데, 검증기가 이 변화를 놓쳐서 잘못된 메모리 주소에 접근할 수 있게 되는 문제입니다. 이는 시스템의 보안 경계를 무너뜨릴 수 있는 위험한 오류입니다.
🇺🇸 원문 (English)
In the Linux kernel, the following vulnerability has been resolved:
bpf: track changes_pkt_data property for global functions
When processing calls to certain helpers, verifier invalidates all
packet pointers in a current state. For example, consider the
following program:
__attribute__((__noinline__))
long skb_pull_data(struct __sk_buff *sk, __u32 len)
{
return bpf_skb_pull_data(sk, len);
}
SEC("tc")
int test_invalidate_checks(struct __sk_buff *sk)
{
int *p = (void *)(long)sk->data;
if ((void *)(p + 1) > (void *)(long)sk->data_end) return TCX_DROP;
skb_pull_data(sk, 0);
*p = 42;
return TCX_PASS;
}
After a call to bpf_skb_pull_data() the pointer 'p' can't be used
safely. See function filter.c:bpf_helper_changes_pkt_data() for a list
of such helpers.
At the moment verifier invalidates packet pointers when processing
helper function calls, and does not traverse global sub-programs when
processing calls to global sub-programs. This means that calls to
helpers done from global sub-programs do not invalidate pointers in
the caller state. E.g. the program above is unsafe, but is not
rejected by verifier.
This commit fixes the omission by computing field
bpf_subprog_info->changes_pkt_data for each sub-program before main
verification pass.
changes_pkt_data should be set if:
- subprogram calls helper for which bpf_helper_changes_pkt_data
returns true;
- subprogram calls a global function,
for which bpf_subprog_info->changes_pkt_data should be set.
The verifier.c:check_cfg() pass is modified to compute this
information. The commit relies on depth first instruction traversal
done by check_cfg() and absence of recursive function calls:
- check_cfg() would eventually visit every call to subprogram S in a
state when S is fully explored;
- when S is fully explored:
- every direct helper call within S is explored
(and thus changes_pkt_data is set if needed);
- every call to subprogram S1 called by S was visited with S1 fully
explored (and thus S inherits changes_pkt_data from S1).
The downside of such approach is that dead code elimination is not
taken into account: if a helper call inside global function is dead
because of current configuration, verifier would conservatively assume
that the call occurs for the purpose of the changes_pkt_data
computation.
📍 영향받는 시스템
Linux kernel (BPF 기능을 사용하는 시스템)
⚔️ 공격 벡터
조작된 BPF 프로그램을 로드하여 검증기를 우회하고 잘못된 메모리 주소에 접근(Out-of-bounds access)
🛡️ 대응 방법
Linux 커널을 최신 보안 패치가 적용된 버전으로 업데이트하십시오.
🔧 검증 코드
출력된 커널 버전이 해당 취약점이 수정된 패치 버전 이후인지 확인하십시오.