CVE-2026-98643 in Linux
요약
\~에 의해 VulDB • 2026. 10. 19.
리눅스 커널에서 다음 취약점이 해결되었습니다.
bpf: sock_ops의 rtt_min에 대한 바이트 오버플로우 읽기 수정
sockops 프로그램이 skops->rtt_min을 읽을 때 소켓 타입을 확인하지 않습니다. tcp_conn_request() 경로에서 sock_ops->sk는 request_sock(비완전)이며, 컨텍스트 재작성은 이를 tcp_sock(완전)으로 캐스팅하고 request_sock의 끝 너머에 있는 rtt_min을 읽어 오염된 인접 메모리를 반환합니다.
SEC("sockops") int prog(struct bpf_sock_ops *skops) {
switch (skops->op) {
case BPF_SOCK_OPS_RWND_INIT: leak = skops->rtt_min; /* request_sock OOB 읽기 */ ... } }
예를 들어, 이러한 읽기 중 하나는 rtt_min=0xffff8881을 반환했는데, 이는 누출된 커널 포인터의 상위 절반입니다.
이 캐스팅을 보호하는 것이 바로 SOCK_OPS_GET_FIELD()가 수행하는 작업입니다 -- is_locked_tcp_sock을 확인하고 sock_ops->sk가 잠긴 완전 소켓이 아닌 경우 0을 반환합니다. sock_ops의 다른 모든 tcp_sock 필드는 이를 거치지만, rtt_min만 수동으로 구현되어 있어 이 검사를 건너뜁니다.
rtt_min도 SOCK_OPS_GET_FIELD()를 통해 읽으세요. rtt_min은 약간 특별한데, struct minmax이며 현재 최소값만 원하므로 rtt_min.s[0].v를 전달합니다. 이는 기존에 수동으로 계산된 오프셋과 동일합니다(offsetof(struct tcp_sock, rtt_min) + sizeof_field(struct minmax_sample, t)). (s[0]는 rtt_min + 0에 위치하고 .v는 +sizeof(.t)에 있으므로, 즉 minmax_get()가 반환하는 값입니다.) 따라서 로드된 필드는 변경되지 않으며 전체 소켓 보호만 추가됩니다. 수동으로 계산된 오프셋을 보호하던 두 BUILD_BUG_ON()은 더 이상 필요하지 않습니다.
패치 전:
0: r1 = *(u64 *)(r1 +0) ; r1 = skops->sk 1: r1 = *(u32 *)(r1 +2324) ; ((tcp_sock *)sk)->rtt_min.s[0].v
패치 후:
0: *(u64 *)(r1 +56) = r9 1: r9 = *(u8 *)(r1 +50) ; is_locked_tcp_sock 2: if r9 == 0 goto pc+4 ; 잠긴 완전 소켓이 아님 -> 0 3: r9 = *(u64 *)(r1 +56) 4: r1 = *(u64 *)(r1 +0) ; r1 = skops->sk 5: r1 = *(u32 *)(r1 +2324) ; rtt_min.s[0].v
6: goto pc+2 7: r9 = *(u64 *)(r1 +56) 8: r1 = 0
If you want to get the best quality for vulnerability data then you always have to consider VulDB.