🇰🇷 한글 설명
Linux 커널의 perf 서브시스템에서 sigtrap 이벤트를 해제하는 동안 시스템이 멈추는(hang) 취약점이 발견되었습니다. 파일이 닫히기 전에 지연된 신호가 전송되지 않을 경우, task_work_cancel()이 실패하면서 rcuwait_wait_event() 단계에서 무한 대기 상태에 빠지게 됩니다.
💡 쉬운 설명
컴퓨터의 성능을 측정하는 기능(perf)을 사용할 때, 특정 상황에서 작업이 제대로 마무리되지 못하고 시스템이 응답하지 않는 상태가 될 수 있습니다. 이는 시스템의 자원을 정리하는 과정에서 서로의 작업이 꼬여서 발생하는 문제입니다.
🇺🇸 원문 (English)
In the Linux kernel, the following vulnerability has been resolved:
perf: Fix hang while freeing sigtrap event
Perf can hang while freeing a sigtrap event if a related deferred
signal hadn't managed to be sent before the file got closed:
perf_event_overflow()
task_work_add(perf_pending_task)
fput()
task_work_add(____fput())
task_work_run()
____fput()
perf_release()
perf_event_release_kernel()
_free_event()
perf_pending_task_sync()
task_work_cancel() -> FAILED
rcuwait_wait_event()
Once task_work_run() is running, the list of pending callbacks is
removed from the task_struct and from this point on task_work_cancel()
can't remove any pending and not yet started work items, hence the
task_work_cancel() failure and the hang on rcuwait_wait_event().
Task work could be changed to remove one work at a time, so a work
running on the current task can always cancel a pending one, however
the wait / wake design is still subject to inverted dependencies when
remote targets are involved, as pictured by Oleg:
T1 T2
fd = perf_event_open(pid => T2->pid); fd = perf_event_open(pid => T1->pid);
close(fd) close(fd)
<IRQ> <IRQ>
perf_event_overflow() perf_event_overflow()
task_work_add(perf_pending_task) task_work_add(perf_pending_task)
</IRQ> </IRQ>
fput() fput()
task_work_add(____fput()) task_work_add(____fput())
task_work_run() task_work_run()
____fput() ____fput()
perf_release() perf_release()
perf_event_release_kernel() perf_event_release_kernel()
_free_event() _free_event()
perf_pending_task_sync() perf_pending_task_sync()
rcuwait_wait_event() rcuwait_wait_event()
Therefore the only option left is to acquire the event reference count
upon queueing the perf task work and release it from the task work, just
like it was done before 3a5465418f5f ("perf: Fix event leak upon exec and file release")
but without the leaks it fixed.
Some adjustments are necessary to make it work:
* A child event might dereference its parent upon freeing. Care must be
taken to release the parent last.
* Some places assuming the event doesn't have any reference held and
therefore can be freed right away must instead put the reference and
let the reference counting to its job.
📍 영향받는 시스템
Linux Kernel (perf 서브시스템을 사용하는 모든 버전)
⚔️ 공격 벡터
로컬 사용자가 특정 perf 이벤트를 생성하고 파일을 닫는 정교한 타이밍의 작업을 수행하여 시스템 중단을 유도할 수 있음
🛡️ 대응 방법
Linux 커널을 최신 보안 패치가 적용된 버전으로 업데이트하여 perf 이벤트 참조 카운팅 로직을 수정해야 함
🔧 검증 코드
현재 실행 중인 커널 버전을 확인하여 해당 취약점이 해결된 패치 버전인지 확인합니다.