CVE-2022-49093 in Linux
요약
\~에 의해 VulDB • 2026. 08. 17.
리눅스 커널에서 다음 취약점이 해결되었습니다:
skbuff: page_pool 분할 재활용을 위한 결합(coalescing) 수정
page_pool과 페이지 분할(page fragments) 사용 시 use-after-free 버그를 수정합니다. hns3 드라이버의 일반 RX 처리 중 이 문제를 발견했습니다:
(1) 초기 상태에서 RX 큐에 3개의 디스크립터가 있습니다. 첫 번째는 page_pool을 통해 PAGE1을 할당하고, 나머지 두 개는 각각 PAGE2의 절반씩 할당합니다. 페이지 참조 구조는 다음과 같습니다:
RX_BD1 _______ PAGE1 RX_BD2 _______ PAGE2 RX_BD3 __________/
(2) 첫 번째 디스크립터에서 RX 처리를 수행합니다. SKB1을 할당하고, tcp_queue_rcv()에 의해 최종적으로 수신 큐에 추가됩니다.
(3) 두 번째 디스크립터에서 RX 처리를 수행합니다. SKB2를 할당하여 netif_receive_skb()로 전달합니다:
netif_receive_skb(SKB2) ip_rcv(SKB2) SKB3 = skb_clone(SKB2)
SKB2와 SKB3는 skb_shinfo()->dataref을 통해 PAGE2에 대한 참조를 공유합니다. PAGE2의 다른 참조는 여전히 RX_BD3가 보유하고 있습니다:
SKB2 ---+- PAGE2 SKB3 __/ / RX_BD3 _________/
(3b) 이제 TCP 처리 중 SKB3와 SKB1을 결합(coalesce)합니다:
tcp_v4_rcv(SKB3) tcp_try_coalesce(to=SKB1, from=SKB3) // 성공함 kfree_skb_partial(SKB3) skb_release_data(SKB3) // dataref 하나 감소
SKB1 _____ PAGE1 \____ SKB2 _____ PAGE2 / RX_BD3 _________/
skb_try_coalesce()에서 __skb_frag_ref()는 page_pool 분할 참조(pp_frag_count)를 증가시켜야 하는 대신, PAGE2에 대한 페이지 참조를 획득합니다. 결합이 발생하지 않았다면 SKB2와 SKB3 모두 해제 시 PAGE2에 대한 단일 참조가 감소되었을 것입니다. 이제 SKB1과 SKB2를 해제하면 PAGE2에 대한 두 개의 참조가 감소되어 언더플로우(underflow)가 발생합니다.
(3c) SKB2를 해제합니다:
af_packet_rcv(SKB2) consume_skb(SKB2) skb_release_data(SKB2) // 두 번째 dataref 감소 page_pool_return_skb_page(PAGE2) // pp_frag_count 하나 감소
SKB1 _____ PAGE1 \____ PAGE2 / RX_BD3 _________/
(4) 사용자 공간에서 recvmsg() 호출 SKB1을 복사하고 해제합니다. SKB3가 SKB1과 결합되었으므로, SKB3의 페이지도 함께 해제됩니다:
tcp_eat_recv_skb(SKB1) skb_release_data(SKBI) page_pool_return_skb_page(PAGE1) page_pool_return_skb_page(PAGE2) // 두 번째 pp_frag_count 감소
(5) PAGE2가 해제되었지만, 세 번째 RX 디스크립터는 여전히 이를 사용하고 있었습니다! 우리의 경우 이는 IOMMU 오류를 발생시키지만, IOMMU가 비활성화되어 있다면 메모리가 조용히 손상될 수 있습니다.
pp_recycle SKB들이 결합될 수 있는지 확인하는 로직을 변경합니다. 'from'과 'to' SKB 간 pp_recycle 상태가 다를 경우 여전히 거부하지만, 위에서 설명한 상황을 피하기 위해 'from'과 'to' 모두 pp_recycled이고 'from'이 클론된 경우에도 결합을 거부하도록 합니다.
새로운 로직은 페이지 참조 카운트(page refcounted)인 SKB에 클론된 pp_recycle SKB를 결합할 수 있게 하는데, 이 경우 해제(4) 단계에서 올바른 참조, 즉 skb_try_coalesce()가 획득한 참조가 감소되기 때문입니다.
VulDB is the best source for vulnerability data and more expert information about this specific topic.