🇰🇷 한글 설명
Linux 커널의 unshare 시스템 콜 구현에서, set_cred_ucounts() 실패 시 설치되지 않은 nsproxy에 대해 put_nsproxy()를 호출하여 네임스페이스 활성 참조 카운트가 잘못 감소하는 문제입니다. 이로 인해 커널 경고가 발생하고 호출자가 사용 중인 네임스페이스가 listns()에서 누락될 수 있습니다. 수정은 실패한 unshare()에서 nsproxy_free()를 사용하도록 변경하는 것입니다.
💡 쉬운 설명
프로그램이 네임스페이스를 분리하는 과정에서 실패했을 때 커널이 잘못된 정리 작업을 수행합니다. 그 결과 커널 경고가 나오고 시스템이 현재 사용 중인 네임스페이스를 올바르게 추적하지 못할 수 있습니다.
🇺🇸 원문 (English)
In the Linux kernel, the following vulnerability has been resolved:
unshare: don't drop active namespace references that were never taken
Active references on the namespaces of an nsproxy are taken when the
nsproxy is installed into a task in switch_task_namespaces() and
copy_namespaces() and dropped again by put_nsproxy() through
deactivate_nsproxy().
But ksys_unshare() calls put_nsproxy() on an nsproxy that was never
installed when set_cred_ucounts() fails. The new namespaces of that
nsproxy go from zero to minus one and the namespaces shared with the
caller lose a reference that belongs to the nsproxy the caller keeps
using:
WARNING: kernel/nscommon.c:171 at __ns_ref_active_put+0x1cd/0x230
nsproxy_ns_active_put
deactivate_nsproxy
ksys_unshare
Afterwards the namespaces the caller lives in aren't listed by listns()
anymore. set_cred_ucounts() only fails when alloc_ucounts() can't
allocate and it only allocates when the real uid of the caller differs
from its effective uid.
Commit cefd55bd2159 ("nsproxy: fix free_nsproxy() and simplify
create_new_namespaces()") separated the two cases on purpose.
nsproxy_free() frees an nsproxy that was prepared but never installed
and that's what a failed setns() uses in put_nsset(). Export it and use
it for a failed unshare() as well.
📍 영향받는 시스템
수정 커밋 이전의 Linux 커널 (해당 패치 적용 전 배포판 커널 전반, 정확한 버전 범위는 확인 필요)
⚔️ 공격 벡터
일반 로컬 사용자가 unshare 시스템 콜을 호출하고 ucounts 할당 실패를 유도할 수 있는 조건에서 발생하며, 주로 안정성 저하 및 네임스페이스 추적 오류 형태로 나타납니다.
🛡️ 대응 방법
배포판의 최신 커널 업데이트를 적용하여 해당 커널 패치(nsproxy_free 사용 수정)가 포함된 버전으로 재부팅합니다.
🔧 검증 코드
출력된 커널 버전을 배포판 보안 공지 또는 upstream 수정 커밋과 비교하여, 패치가 포함된 버전인지 확인합니다. 패치 포함 여부가 불명확하면 배포판 보안 권고를 확인해야 합니다.