🇰🇷 한글 설명
Linux 커널의 OCFS2 클러스터 구성 요소에서 o2hb_region_pin() 함수가 스핀락을 보유한 상태에서 수면(sleep)을 유발하여 커널 버그 및 데드락을 발생시키는 취약점입니다. 이 문제는 잠금 순서 역전과 리소스 누수를 포함하며, 패치를 통해 잠금 해제 후 작업을 수행하도록 수정되었습니다.
💡 쉬운 설명
컴퓨터의 핵심 운영체제(커널)가 데이터를 처리하는 과정에서 서로 맞물린 자물쇠를 풀지 못해 시스템이 멈추거나(데드락), 오류가 발생하는 문제입니다. 이로 인해 시스템이 갑자기 중단되거나 불안정해질 수 있습니다.
🇺🇸 원문 (English)
In the Linux kernel, the following vulnerability has been resolved:
ocfs2: cluster: don't sleep while holding o2hb_live_lock in o2hb_region_pin()
Patch series "ocfs2: cluster: o2hb_region_pin() fixes", v2.
This series fixes three related issues in o2hb_region_pin(), all are from
the original implementation in commit: 58a3158a5d17 ("ocfs2/cluster:
Pin/unpin o2hb regions"):
1) It is called with o2hb_live_lock (a spinlock) held, but the
underlying configfs_depend_item() sleeps (takes inode rwsem and
pins the filesystem). This triggers BUG under
CONFIG_DEBUG_ATOMIC_SLEEP.
2) When called from the configfs drop_item callback, it creates a
lock order inversion: parent inode_lock -> configfs root
inode_lock, which can deadlock against subsystem unregistration
paths taking root -> parent.
3) If pinning fails partway through o2hb_region_inc_user(), the
o2hb_dependent_users counter is leaked and partially-pinned
regions are never released, leaving heartbeat regions
unprotected on subsequent mounts.
Patch 1 reworks o2hb_region_pin() to drop o2hb_live_lock across each
sleeping configfs_depend_item() call, using a config_item reference to
keep the region alive while unlocked.
Patch 2 adds a from_callback parameter to select
configfs_depend_item_unlocked() when called from configfs context,
avoiding the inode_lock nesting.
Patch 3 fixes the error path in o2hb_region_inc_user() to unpin and
decrement the counter on failure.
This patch (of 3):
o2hb_region_pin() is always called with the o2hb_live_lock spinlock held
(from o2hb_region_inc_user() and o2hb_heartbeat_group_drop_item()), but it
calls o2nm_depend_item() -> configfs_depend_item(), which sleeps: it pins
the configfs filesystem and takes the configfs root inode rwsem. Under
CONFIG_DEBUG_ATOMIC_SLEEP this triggers:
BUG: sleeping function called from invalid context at kernel/locking/rwsem.c
in_atomic(): 1, ... name: mount.ocfs2
down_write
configfs_depend_item
o2hb_region_pin
o2hb_region_inc_user
o2hb_register_callback
dlm_register_domain_handlers
...
ocfs2_dlm_init
ocfs2_mount_volume
ocfs2_fill_super
Rework o2hb_region_pin() to pin one region at a time with the lock dropped
across the sleeping call: under o2hb_live_lock find the next eligible
region and take a config_item reference to keep it alive, drop the lock,
call o2nm_depend_item(), then retake the lock and record the pin. The
config_item_put() is done with the lock released as well, since
o2hb_region_release() also acquires o2hb_live_lock and can sleep. The
region list may change while unlocked, so the scan restarts from the top
after each pin. Local heartbeat still pins only the matching region;
global heartbeat pins all eligible regions.
The unpin path is unaffected: configfs_undepend_item() only takes a
spinlock and does not sleep.
📍 영향받는 시스템
Linux Kernel (OCFS2 클러스터 기능을 사용하는 시스템)
⚔️ 공격 벡터
로컬 공격자가 특정 파일 시스템 구성(configfs)을 조작하여 커널의 잠금 순서 역전을 유도함으로써 데드락을 발생시킬 수 있음
🛡️ 대응 방법
Linux 커널을 최신 보안 패치가 적용된 버전으로 업데이트하십시오.
🔧 검증 코드
출력된 커널 버전이 해당 취약점이 해결된 패치 시리즈가 적용된 버전인지 확인하십시오.