🇰🇷 한글 설명
Linux 커널의 Ceph 파일 시스템에서 __kick_flushing_caps() 함수 실행 중 발생하는 Use-After-Free(UAF) 취약점입니다. 락(lock)을 해제하고 메시지를 보내는 과정에서 경쟁 상태(Race Condition)가 발생하여, 이미 해제된 메모리 주소에 접근함으로써 시스템 오류나 권한 상승을 초래할 수 있습니다.
💡 쉬운 설명
데이터를 정리하는 과정에서 잠시 문을 열어두는 사이, 다른 작업이 이미 사용 중인 데이터를 삭제해 버리는 문제입니다. 그 후 원래 작업이 삭제된 데이터를 다시 사용하려고 시도하면서 시스템에 문제가 발생합니다.
🇺🇸 원문 (English)
In the Linux kernel, the following vulnerability has been resolved:
ceph: fix UAF in __kick_flushing_caps() on cf entry freed during unlock
list_for_each_entry() iterates ci->i_cap_flush_list but drops
i_ceph_lock to send cap messages. During the unlock window,
handle_cap_flush_ack() can acquire i_ceph_lock, detach cf entries
with tid <= flush_tid from the list, release i_ceph_lock, and free
them via ceph_free_cap_flush() outside any lock. When the original
thread reacquires i_ceph_lock and the for-loop macro advances via
cf = list_next_entry(cf, i_list), it dereferences cf->i_list.next
on freed memory.
The race timeline:
__kick_flushing_caps() handle_cap_flush_ack()
----------------------- -----------------------
holds i_ceph_lock <---
iterates to cf (tid=10)
prepares FLUSH message
drops i_ceph_lock <---
__send_cap() ── FLUSH(tid=10)
MDS sends FLUSH_ACK(tid=10)
---> acquires i_ceph_lock
cf->tid(10) <= flush_tid(10),
detaches cf from i_cap_flush_list
drops i_ceph_lock
ceph_free_cap_flush(cf) <- frees it!
acquires i_ceph_lock <---
for-loop advances:
cf = list_next_entry(cf, i_list)
-- UAF on freed cf->i_list.next
The cf was just sent by __kick_flushing_caps itself via __send_cap().
The MDS may respond with FLUSH_ACK quickly enough that
handle_cap_flush_ack() frees cf before __kick_flushing_caps can
finish the iteration.
Fix by converting to a manual while loop: save the next pointer
under i_ceph_lock before dropping it, then use the saved pointer
after reacquiring, so the potentially-freed cf is never accessed again.
📍 영향받는 시스템
Linux kernel (Ceph file system component)
⚔️ 공격 벡터
MDS(Metadata Server)로부터 빠른 FLUSH_ACK 응답을 유도하여 경쟁 상태를 유발하는 네트워크 기반 공격
🛡️ 대응 방법
Linux 커널을 최신 보안 패치가 적용된 버전으로 업데이트하거나, 해당 함수를 수동 while 루프로 수정하여 메모리 참조 방식을 변경해야 합니다.
🔧 검증 코드
현재 실행 중인 커널 버전과 Ceph 모듈 정보를 확인하여 보안 패치 적용 여부를 검토합니다.
uname -r && modinfo ceph | grep version 2>/dev/null || dmesg | grep -i ceph