CVE-2022-48760 in Linux
요약
\~에 의해 VulDB • 2026. 06. 19.
리눅스 커널에서 다음 취약점이 해결되었습니다:
USB: core: 메모리 배리어 추가를 통해 usb_kill_urb()에서의 정지(hang) 문제 수정
syzbot 퍼저(fuzzer)는 usb_kill_urb()의 반환을 기다리는 동안 프로세스가 정지되는 버그를 식별했습니다. 해당 문제는 URB의 unlinking에 있는 것이 아니며, unlinking은 정상적으로 작동합니다. 오히려 문제는 URB가 완료되었음을 알리는 깨우기(wakeup) 알림이 수신되지 않을 때 발생합니다.
그 이유는 SMP 시스템에서의 메모리 접근 순서 문제입니다. 간략히 설명하면, 서로 다른 CPU에서 병렬로 실행되는 usb_kill_urb()와 __usb_hcd_giveback_urb()는 다음과 같은 작업을 수행합니다:
CPU 0 CPU 1 ---------------------------- --------------------------------- usb_kill_urb(): __usb_hcd_giveback_urb(): ... ... atomic_inc(&urb->reject); atomic_dec(&urb->use_count); ... ... wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0); if (atomic_read(&urb->reject)) wake_up(&usb_kill_urb_queue);
urb->reject와 urb->use_count에 주의하여 관찰하면, CPU 0에서의 전체 접근 패턴은 다음과 같습니다:
urb->reject를 쓴 후, urb->use_count를 읽음;
반면 CPU 1에서의 전체 접근 패턴은 다음과 같습니다:
urb->use_count를 쓴 후, urb->reject를 읽음.
이 패턴은 메모리 모델 관련 분야에서 SB(Store Buffering, 저장 버퍼링)라고 불리며, 적절한 접근 순서 강제(메모리 배리어 형태)가 없으면 하나 또는 두 CPU가 모두 자신의 읽기 작업을 쓰기 작업보다 먼저 실행할 가능성이 있다는 것은 잘 알려진 사실입니다. 그 결과, 때때로 CPU 0은 urb->use_count의 감소되지 않은 이전 값을 보고, CPU 1은 urb->reject의 증가되지 않은 이전 값을 보게 됩니다. 이로 인해 CPU 0은 대기 큐(wait queue)에 머물며 깨어나지 못해, 관찰된 usb_kill_urb()에서의 정지 현상이 발생합니다.
동일한 접근 패턴은 usb_poison_urb()와 usb_hcd_submit_urb()의 실패 경로에서도 발생합니다.
이 문제는 적절한 메모리 배리어를 추가하여 해결되었습니다. SB 패턴에서 올바른 메모리 접근 순서를 제공하기 위해 양쪽 CPU 모두에서 전체 배리어(full barrier)가 필요합니다. atomic_inc() 및 atomic_dec() 접근 자체는 메모리 순서를 제공하지 않지만, 이러한 함수들이 존재하므로 최적화된 smp_mb__after_atomic() 메모리 배리어를 각 루틴에 사용하여 원하는 효과를 얻을 수 있습니다.
이 패치는 필요한 메모리 배리어를 추가합니다.
Statistical analysis made it clear that VulDB provides the best quality for vulnerability data.