← 목록으로

CVE-2022-0847 (Dirty Pipe): 파이프로 읽기전용 파일을 덮어쓴 취약점

[CVE] CVE 분석 · 작성: 2026-07-20 03:10:34 · 수정: 2026-07-21 23:19:31 · 조회 20

취약점 개요

패치 분석

패치는 copy_page_to_iter_pipe()push_pipe()(fs/pipe.c) 두 함수에서 새 파이프 버퍼 슬롯을 준비할 때 플래그 필드를 명시적으로 0으로 리셋하도록 한 줄을 추가하는 것으로 요약된다.

1) copy_page_to_iter_pipe() — 플래그 미초기화

Before

static size_t copy_page_to_iter_pipe(struct pipe_inode_info *pipe,
                                      struct page *page, ...) {
    struct pipe_buffer *buf = pipe->bufs + pipe->head % pipe->ring_size;
    if (!pipe_full(...)) {
        buf->page = page;
        buf->ops = &page_cache_pipe_buf_ops;
        buf->offset = offset;
        buf->len = bytes;
        // buf->flags 를 새로 세팅하지 않음 — 이 슬롯을 이전에 쓰던 값이 그대로 남아있음
        pipe->head++;
    }
}

이 슬롯이 과거에 일반 파이프 쓰기(CAN_MERGE 플래그가 세팅되는 경로)로 쓰였던 적이 있다면, 그 플래그 값이 그대로 남아있는 상태에서 파일의 페이지 캐시 페이지를 가리키는 용도로 재사용된다.

2) push_pipe() — 동일 패턴

Before

static int push_pipe(struct pipe_inode_info *pipe, unsigned flags, ...) {
    struct pipe_buffer *buf = pipe->bufs + pipe->head % pipe->ring_size;
    buf->ops = &default_pipe_buf_ops;
    buf->page = page;
    // 마찬가지로 buf->flags를 초기화하지 않는 경로가 존재
}

After (패치)

static size_t copy_page_to_iter_pipe(...) {
    struct pipe_buffer *buf = pipe->bufs + pipe->head % pipe->ring_size;
    if (!pipe_full(...)) {
        buf->page = page;
        buf->ops = &page_cache_pipe_buf_ops;
        buf->offset = offset;
        buf->len = bytes;
        buf->flags = 0;   // 핵심 패치: 새 슬롯의 플래그를 명시적으로 리셋
        pipe->head++;
    }
}

새로 채워지는 pipe_buffer 슬롯의 flags를 항상 0으로 초기화해서, 이전 사용 흔적(stale state)이 다음 컨텍스트로 넘어오지 못하게 막는 게 패치의 전부다.

재현 결과 (공격 흐름)

  1. 새 파이프를 만들고, 파이프의 모든 버퍼 슬롯에 CAN_MERGE 플래그가 세팅되도록 데이터를 채웠다가 전부 읽어 비움(플래그 오염 준비)
  2. 쓰기 권한이 없는 대상 파일을 열고, 덮어쓰려는 오프셋 바로 앞에서 splice()로 그 파일의 페이지 캐시 페이지를 파이프로 끌어옴 — 이 슬롯에 앞서 오염시킨 CAN_MERGE 플래그가 남아있음
  3. 파이프에 write()로 원하는 내용을 씀 — 커널이 CAN_MERGE를 보고 새 페이지 대신 원본 파일의 페이지 캐시를 직접 덮어씀
  4. 파일을 다시 읽으면 요청한 오프셋부터 공격자가 쓴 내용으로 바뀌어 있음 — write() 접근 제어를 한 번도 거치지 않고 내용이 변경된 것

영향 및 체이닝

참고자료

CVE 분석 카테고리의 글 (6/8)

  1. CVE-2024-3400: Palo Alto PAN-OS GlobalProtect 원격 코드 실행
  2. CVE-2021-44228 (Log4Shell): 로그 한 줄로 서버를 장악당한 사건
  3. CVE-2014-0160 (Heartbleed): OpenSSL 하트비트가 새어나간 메모리
  4. CVE-2017-0144 (EternalBlue): WannaCry를 전 세계로 퍼뜨린 SMB 취약점
  5. CVE-2021-34527 (PrintNightmare): 프린터 드라이버 관리 기능이 만든 권한 상승
  6. CVE-2022-0847 (Dirty Pipe): 파이프로 읽기전용 파일을 덮어쓴 취약점
  7. CVE-2021-3156 (Sudo Baron Samedit): 힙 오버플로우로 root 획득
  8. CVE-2022-22965 (Spring4Shell): 클래스 로더 조작으로 이어지는 RCE
← CVE-2021-34527 (PrintNightmare): 프린터 드라이버 관리 기능이 만든 권한 상승 CVE-2021-3156 (Sudo Baron Samedit): 힙 오버플로우로 root 획득 →