🇰🇷 한글 설명
리눅스 커널의 메모리 관리(mm) 서브시스템에서 free_swap_and_cache()와 swapoff() 함수 간의 레이스 컨디션 취약점이 발견되었습니다. 이로 인해 swapoff()가 swap_info_struct를 해제하는 동안 다른 스레드가 해제된 메모리에 접근하여 시스템 불안정성을 초래할 수 있습니다.
💡 쉬운 설명
컴퓨터가 메모리를 정리하는 과정에서 두 작업이 동시에 충돌하여 이미 삭제된 메모리 영역을 건드릴 수 있는 문제입니다. 이로 인해 시스템이 멈추거나 예기치 않은 오류가 발생할 수 있습니다.
🇺🇸 원문 (English)
In the Linux kernel, the following vulnerability has been resolved:
mm: swap: fix race between free_swap_and_cache() and swapoff()
There was previously a theoretical window where swapoff() could run and
teardown a swap_info_struct while a call to free_swap_and_cache() was
running in another thread. This could cause, amongst other bad
possibilities, swap_page_trans_huge_swapped() (called by
free_swap_and_cache()) to access the freed memory for swap_map.
This is a theoretical problem and I haven't been able to provoke it from a
test case. But there has been agreement based on code review that this is
possible (see link below).
Fix it by using get_swap_device()/put_swap_device(), which will stall
swapoff(). There was an extra check in _swap_info_get() to confirm that
the swap entry was not free. This isn't present in get_swap_device()
because it doesn't make sense in general due to the race between getting
the reference and swapoff. So I've added an equivalent check directly in
free_swap_and_cache().
Details of how to provoke one possible issue (thanks to David Hildenbrand
for deriving this):
--8<-----
__swap_entry_free() might be the last user and result in
"count == SWAP_HAS_CACHE".
swapoff->try_to_unuse() will stop as soon as soon as si->inuse_pages==0.
So the question is: could someone reclaim the folio and turn
si->inuse_pages==0, before we completed swap_page_trans_huge_swapped().
Imagine the following: 2 MiB folio in the swapcache. Only 2 subpages are
still references by swap entries.
Process 1 still references subpage 0 via swap entry.
Process 2 still references subpage 1 via swap entry.
Process 1 quits. Calls free_swap_and_cache().
-> count == SWAP_HAS_CACHE
[then, preempted in the hypervisor etc.]
Process 2 quits. Calls free_swap_and_cache().
-> count == SWAP_HAS_CACHE
Process 2 goes ahead, passes swap_page_trans_huge_swapped(), and calls
__try_to_reclaim_swap().
__try_to_reclaim_swap()->folio_free_swap()->delete_from_swap_cache()->
put_swap_folio()->free_swap_slot()->swapcache_free_entries()->
swap_entry_free()->swap_range_free()->
...
WRITE_ONCE(si->inuse_pages, si->inuse_pages - nr_entries);
What stops swapoff to succeed after process 2 reclaimed the swap cache
but before process1 finished its call to swap_page_trans_huge_swapped()?
--8<-----
📍 영향받는 시스템
Linux Kernel (swap 관련 메모리 관리 기능이 활성화된 버전)
⚔️ 공격 벡터
특정 타이밍에 swapoff()와 free_swap_and_cache()를 동시에 유도하는 정교한 레이스 컨디션 공격
🛡️ 대응 방법
get_swap_device() 및 put_swap_device()를 사용하여 참조 카운트를 관리하도록 커널을 최신 보안 패치 버전으로 업데이트
🔧 검증 코드
출력된 커널 버전을 확인하여 해당 취약점이 해결된 최신 패치 버전인지 확인합니다.