SK쉴더스 로고
ADT캡스캡스홈
SK쉴더스

리눅스 커널 epoll 로컬 권한상승 취약점 (CVE-2026-46242)

EQST Now | 2026.07.08

NOW Briefing

Brief 1 리눅스 커널의 핵심 I/O 감시 기능인 epoll에서 경쟁 조건 기반 use-after-free(해제된 메모리 재사용) 취약점 Bad Epoll(CVE-2026-46242)이 공개됐습니다. 리눅스 공식 커널(메인라인) 6.4 이상과 6.6대 이후 안드로이드가 영향을 받습니다.
Brief 2 별도 권한이 없는 로컬 사용자가 이 취약점을 악용하면 커널 메모리를 장악하고 root 권한까지 획득할 수 있습니다. 2026년 7월 3일 공개된 PoC는 제작자 테스트 환경에서 약 99% 확률로 익스플로잇에 성공했습니다.
Brief 3 설정으로 우회할 방법은 없으므로, 패치가 반영된 배포판 커널로 즉시 업데이트해야 합니다. 공유 호스팅·CI 러너·컨테이너처럼 비권한 로컬 실행이 몰리는 환경을 우선 점검해야 합니다.

리눅스 커널 epoll 로컬 권한상승 취약점 (CVE-2026-46242)

■ 개요

epoll은 리눅스 커널이 다수의 소켓·파일 디스크립터에서 발생하는 I/O 이벤트를 한꺼번에 감시하는 핵심 기능으로, 거의 모든 서버 데몬과 런타임이 내부적으로 사용합니다. Bad Epoll(CVE-2026-46242)은 이 epoll이 파일을 정리하는 경로에 존재하는 경쟁 조건 취약점입니다. 두 개의 종료(close) 경로가 동시에 실행되면서, 한쪽이 아직 사용 중인 커널 객체를 다른 쪽이 해제해 버리는 구조입니다.

이 구조가 도입된 영향 범위는 메인라인 기준 6.4 이상 커널이며, 취약점을 유발한 커밋은 2023년 4월에 들어갔습니다. 6.6 계열 이후를 쓰는 안드로이드 단말(Pixel 포함)도 대상입니다. 엔터프라이즈 배포판은 커밋을 구버전 커널로 백포트하는 경우가 많아, 5.14 기반 EL9 계열처럼 표면상 "6.4 미만"인 커널도 영향을 받을 수 있습니다.

이 범위에 포함된 커널에서 익스플로잇에 성공하면 8바이트 크기의 잘못된 쓰기가 커널의 struct file 객체 장악으로 확대되고, 이어서 임의 커널 읽기와 제어 흐름 탈취를 거쳐 root 권한 획득으로 이어집니다. 원격 공격은 아니지만 별도 상승 권한 없이 로컬 계정만 있으면 되므로, 여러 사용자가 한 커널을 공유하는 환경에서 위험도가 특히 높습니다.

로컬 권한상승 취약점임에도 위험도가 큰 상황에서 패치는 2026년 4월 24일 별도 공지 없이 머지됐고, 7월 3일 Google kernelCTF에 제출된 익스플로잇과 근본 원인 write-up이 공개되면서 악용 문턱이 낮아졌습니다. 현재까지 실제 공격에 악용된 사례는 보고되지 않았지만, 성공률 높은 공개 PoC가 이미 존재하는 만큼 즉시 대응해야 합니다.

■ 요약

항목 내용
CVE ID CVE-2026-46242 (Bad Epoll)
CVSS 점수 CVSS v3.1 7.8 / High (레드햇 산정 7.0)
취약점 유형 CWE-416, 경쟁 조건 기반 use-after-free (로컬 권한상승)
영향/위험 • 비권한 로컬 사용자의 root 권한 획득 가능
• 8바이트 UAF 쓰기 → struct file 장악 → 커널 제어 흐름 탈취
• 리눅스 서버·데스크톱 및 안드로이드 단말 영향
• 공개 PoC 성공률 제작자 테스트 환경 기준 약 99%
취약 버전 메인라인 6.4 이상(도입 커밋 58c9b016e128), 6.6대 이후 안드로이드, 백포트된 EL9 계열 등
패치 버전 수정 커밋 a6dc643c6931(2026-04-24) 및 이를 포함한 배포판 커널

■ 기술 분석

Bad Epoll의 근본 원인은 fs/eventpoll.cep_remove() 함수에 있습니다. 이 함수는 epoll 항목을 제거할 때 파일과 epoll 사이의 연결 정보(file->f_ep)를 file->f_lock 잠금 아래에서 먼저 비웁니다. 그런데 그 뒤에도 같은 file 객체를 계속 사용해 hlist_del_rcu()와 잠금 해제까지 진행합니다.

이 순서 때문에 다른 CPU에서 동시에 실행되는 파일 해제 경로(__fput())가 방금 비워진 연결 정보를 보고 "이미 epoll 정리가 끝났다"고 판단합니다. 이후 eventpoll_release_file()을 건너뛰고 곧장 파일을 반납해, 아직 ep_remove()가 쓰고 있는 struct eventpoll 객체를 해제해 버립니다. 두 경로가 겹치는 경쟁 구간은 약 6개 기계 명령어에 불과하지만, 공개 PoC는 이 좁은 창을 안정적으로 파고듭니다.

📌 NOTE

두 종료 경로가 부딪히는 "close-vs-close" 구조라 단일 프로세스만으로는 재현되지 않고, 여러 epoll 객체를 짝지어 한 쌍이 경쟁을 유발하고 다른 쌍이 UAF 쓰기의 피해 객체가 됩니다.

근본 원인이 파일 참조를 고정하지 않은 상태에서 정리 경로가 진행되는 데 있으므로, 패치는 잠금을 잡기 전에 파일 참조를 먼저 고정(pin)하는 방식으로 경쟁을 차단합니다. epi_fget()으로 참조를 획득하고 __free(fput) 가드로 범위 종료 시 자동 반납하도록 바꿔, 참조를 얻지 못하면(=이미 해제 중이면) 곧바로 반환합니다. 참조가 살아 있는 동안에는 다른 경로가 파일을 해제할 수 없습니다.

/* [패치 전] fs/eventpoll.c — ep_remove() */
struct file *file = epi->ffd.file;
/* ... 생략 ... */
spin_lock(&file->f_lock);        // file 참조를 고정하지 않은 채 잠금
if (epi->dying) {
    spin_unlock(&file->f_lock);
    return;
}
ep_remove_file(ep, epi, file);   // 동시 __fput()가 file을 해제하면 UAF

/* [패치 후] */
struct file *file __free(fput) = NULL;
/* ... 생략 ... */
file = epi_fget(epi);            // 상단에서 참조 획득(pin)
if (!file)
    return;                      // 이미 해제 중이면 조기 반환
spin_lock(&file->f_lock);
ep_remove_file(ep, epi, file);

■ PoC

기술 분석에서 확인한 8바이트 UAF 쓰기는 공개 PoC(J-jaeyoung/bad-epoll)에서 크로스캐시(cross-cache, 서로 다른 슬랩 캐시 사이의 메모리 재할당)로 확대돼 해제된 struct file을 공격자 데이터로 채웁니다. 이를 발판으로 임의 커널 읽기와 제어 흐름 탈취까지 이어 갑니다. 아래 예시는 실제 익스플로잇이 아니라 공개 PoC의 검증 관점을 방어용으로 단순화한 것으로, 참조를 고정하지 않아 권한 경계가 무너지는 근본 원인만 로직 수준으로 담았습니다.

/* 방어용으로 단순화한 로직 — 실행 불가 */
void ep_remove_flawed(epitem *epi) {
    file = epi->file;          // 참조를 "고정"하지 않고 그대로 사용
    clear_link(file);          // f_ep 연결을 먼저 비움

    // ── 이 지점에서 다른 스레드의 __fput()가 file 해제 가능 ──
    // ... 경쟁 유발 세부 순서 생략 ...

    hlist_del_rcu(file);       // 이미 해제됐을 수 있는 메모리에 8바이트 쓰기 → UAF
}

⚠️ WARN

이 취약점은 이미 패치가 공개됐지만 성공률 높은 공개 익스플로잇이 존재합니다. 멀티테넌트(하나의 커널·시스템을 여러 고객이 나눠 쓰는 구조)·공유 커널 환경에서는 미패치 상태 자체를 권한 탈취 가능 상태로 간주하고 우선순위를 높여야 합니다.

■ 탐지 및 점검

• 공개 익스플로잇 존재 여부와 무관하게 uname -r로 실행 중인 커널 버전을 확인하고, 배포판 보안 공지의 수정 버전과 대조해 미패치 여부를 판별합니다.

• 커널 소스가 있는 시스템에서는 grep -n 'epi_fget\|__free(fput)' fs/eventpoll.cep_remove()에 수정 패턴이 반영됐는지 확인합니다.

• 공유 호스팅·CI 러너·컨테이너 호스트 등 비권한 로컬 실행이 몰리는 노드를 식별해 우선 점검 대상으로 삼습니다.

• 이 취약점은 로컬 경쟁 조건이라 네트워크 IoC가 없으므로, 탐지는 런타임 시그니처가 아니라 커널 버전·패치 상태 인벤토리로 판단합니다.

✅ CHECK

배포판 벤더가 수정 버전을 릴리스했는데 아직 반영하지 않았다면, 해당 호스트는 취약한 것으로 간주하고 조치 대상에 포함해야 합니다.

■ 대응 방안

• 미패치 여부가 확인되면 배포판이 배포한 패치 커널로 즉시 업데이트하고 재부팅해 수정 커밋이 반영되도록 합니다.

• 설정으로 우회할 방법은 없습니다. epoll은 필수 시스템 호출 표면이라 비활성화할 수 없으므로 패치가 유일한 근본 대응입니다.

• 즉시 재부팅이 어려운 운영 서버는 KernelCare 등 리부트리스 패치(재부팅 없이 적용하는 커널 패치, KCARE-27500) 적용 가능 여부를 확인하고, 그 전까지 비권한 로컬 실행 주체를 최소화합니다.

• 일반 사용자 관점에서 직접 조치할 표면은 없지만, 자신이 쓰는 리눅스 배포판·안드로이드 단말의 보안 업데이트를 즉시 적용해야 합니다.

💡 TIP

공유 커널을 여러 테넌트가 함께 쓰는 환경에서는 패치 적용까지 신뢰할 수 없는 로컬 코드 실행을 격리하고, 계정 발급 범위를 줄이는 것이 노출 창을 좁히는 실질적 완화 조치입니다.

[참고 자료]

Bad Epoll (CVE-2026-46242) 기술 분석 — TuxCare

Bad Epoll: a 6-instruction race to root — Zero Hunt

CVE-2026-46242 — Ubuntu Security

ep_remove() 수정 커밋 a6dc643c6931 — torvalds/linux

J-jaeyoung/bad-epoll — 공개 PoC·write-up

  • #EQST_NOW
  • #취약점

관련 서비스

더 많은 보안 인사이트

SK쉴더스 유튜브 채널에서 확인하세요.

SK쉴더스 유튜브 채널에서 확인하세요.
보안 트렌드와 대응방법

매월 뉴스레터로 확인하세요.

매월 뉴스레터로 확인하세요.