LWN Weekly Report: 2026년 10월 22일 주요 뉴스

이번 주 LWN.net 위클리 에디션(10월 22일자) 주요 내용이다. 10월 18일 나온 커널 7.3은 LLM 보조 기여에 힘입어 커밋 수, 개발자 수, 첫 기여자 수에서 모두 역대 기록을 갈아치웠고, LWN은 자동 패치 리뷰가 실제로 버그를 줄이고 있는지 처음으로 데이터를 들여다봤다. LPC 2026에서는 Android 커널의 벤더 훅 800개, 재현 가능한 빌드와 공존하는 Merkle 트리 기반 모듈 서명, 1990년대식 전역 뮤텍스를 깨고 netlink로 옮겨 간 NFS 서버가 다뤄졌다. Kangrejos 2026에서는 필드 이름을 라이프타임으로 쓰는 자기 참조 구조체, XArray의 Rust 재작성, 정수 오버플로를 panic 대신 보고하는 컴파일러 플래그가 나왔다. 여기에 SUSE의 시스템 전역 setuid 비활성화 작업과 Nix flakes의 현재 위치까지 정리한다.

커널 7.3 개발 통계

리누스 토발즈는 10월 18일, 평소의 9주 개발 주기를 마치고 7.3을 릴리스했다. 다음 장기 지원(LTS) 커널이 될 것으로 예상되는 이번 릴리스는 LLM 보조 기여에 힘입어 거의 모든 기록을 깼다. 프로젝트 역사상 처음으로 전체 커밋이 2만 건을 넘었다.

항목7.3비고
머지 제외 커밋18,765전체 커밋은 사상 첫 2만 건 돌파
추가/삭제 라인약 920,000 / 270,000순증 약 65만 줄
개발자3,021명7.2가 세운 2,652명 기록을 한 주기 만에 경신
첫 기여자807명전체 개발자의 4분의 1 이상
식별된 고용주232곳“(Unknown)”이 20.5%로 1위
Reviewed-by 비율50.9%몇 주기 이어지던 하락세가 반전
linux-next 대기 패치약 16,0007.3 때보다 많아 기록은 또 깨질 전망

체인지셋 기준 1위는 binfmt_misc를 크게 개선하고 VFS 전반을 고친 Christian Brauner(216건)다. 2위 Bui Duc Phuc(206건)는 7.1에서 처음 등장해 사운드 드라이버 수정을 주로 했고, 3위 Pengpeng Hou(165건)도 7.0부터 보인 신인이다. 지금까지 커밋이 3건뿐이던 Pan Chuang(150건)이 드라이버 정리 패치를 대량으로 넣은 것도 눈에 띈다. 변경 라인 기준으로는 기계 생성 amdgpu 레지스터 정의 5개 커밋을 넣은 Aurabindo Pillai가 12.5%를 차지했다.

테스터 쪽에서는 AMD 그래픽 드라이버 변경을 63일 동안 하루 4건꼴로 테스트한 Dan Wheeler(261건)가 압도적이다. 리뷰어 1위 Konrad Dybcio는 Qualcomm 드라이버와 디바이스 트리 변경 474건, 하루 7건 이상을 리뷰했다.

버그 리포터의 절반은 자동화 시스템

Reported-by 태그는 1,411개 커밋(7.5%)에 붙었다. 1년 전에는 존재하지도 않던 Sashiko가 그중 19.4%로 1위다. 자동화 시스템을 모두 합치면 크레딧이 붙은 버그 리포트의 절반 가까이를 차지한다.

리포터건수비율
Sashiko30419.4%
Syzbot23915.3%
kernel test robot895.7%
Vega835.3%
Nicholas Carlini412.6%
TencentOS Corvus AI130.8%
autonomouscodesecurity@microsoft.com90.6%

고용주 통계에서는 중국 Kylin OS를 만드는 Kylinsoft(624건, 3.3%)가 급부상했다. 7.3에 기여한 이 회사 소속 개발자는 92명인데 대부분 몇 건씩만 넣었고, 집단으로 LLM이 찾아낸 버그 목록을 처리하는 것으로 보인다. 이들 중 상당수가 이번 주기에 처음 커널에 기여했다.

자동 리뷰는 정말 버그를 줄이고 있나

새 기여자 상당수는 LLM으로 고치는 코드를 실제로 이해하지 못하고, 이는 패치 품질과 장기 유지보수성에 대한 우려로 이어진다. 반대편에는 자동 패치 리뷰 덕분에 들어오는 코드 품질이 올라갔다는 주장이 있다. 많은 버그가 드러나는 데 몇 년이 걸리니 확실한 답은 아직 없지만, Jonathan Corbet은 Fixes 태그로 초기 신호를 살펴봤다.

지표의미추세
직전 릴리스 버그 수정7.3 커밋 중 7.2에서 들어온 버그를 고친 것절대 수는 안정적. 패치 총량이 늘었으니 비율로는 하락
같은 주기 내 버그 수정머지 창에서 들어와 릴리스 전에 고쳐진 버그7.1부터 비율이 떨어지기 시작해 최근 더 가파르게 하락

코드가 널리 테스트되자마자 드러나는 종류의 버그를 자동 리뷰가 미리 걸러내고 있을 가능성을 시사한다. 버그는 그대로 들어오는데 찾아서 고치는 속도가 느려졌다는 해석도 가능하지만, 전반적인 버그 발견 속도가 빨라진 상황을 생각하면 그럴 가능성은 낮다는 게 Corbet의 판단이다. 적어도 명백한 버그에 관해서는 커널에 들어가는 코드 품질이 좋아지고 있을지도 모른다는 것이 잠정 결론이다.

Android 커널의 벤더 훅

LPC 2026 Android 트랙에서 Todd Kjos가 벤더 훅(vendor hook)이 어떻게 쓰이는지 빠르게 정리했다. 현재 가장 많은 Android 기기가 쓰는 커널은 6.6이고, 6.18은 주로 플래그십에 들어간다. Android 6.6 커널이 들고 있는 out-of-tree 패치는 3,100개가 조금 넘는다.

분류패치 수내용
백포트1,531새 커널 릴리스의 기능을 가져온 것
“from list”287메일링 리스트에서 논의 중이지만 아직 메인라인에 없는 것
순수 Android1,306 (약 42%)업스트림에 없고 갈 예정도 없는 것. 3분의 1 이상이 벤더 훅, 나머지는 주로 빌드·설정 변경. 15%는 벤더 훅용 심볼 export

벤더 훅은 가장 낮은 수준에서 보면 Android 커널에 추가된 특수 목적 트레이스포인트다. 벤더의 기기는 이 트레이스포인트에 붙는 전용 커널 모듈을 로드해 그 지점의 제어 흐름을 가로챈다.

trace_android_vh_feature_name(parameters);

붙은 훅은 자료구조를 바꾸고, 새 코드를 끼워 넣고, 메인라인 코드를 건너뛸 수도 있다. 사실상 제약이 거의 없는 커널 코드다. Android는 이 훅들의 ABI를 안정적으로 유지하려 하는데, Kjos는 그게 커널 변경을 자주 제약한다고 했다.

벤더 훅의 절반 가까이는 메모리 관리와 CPU 스케줄러에 있다. 벤더들이 제품 차별화에 가장 공을 들이는 곳이다. 가장 복잡한 훅은 메인라인의 PELT(per-entity load tracking)를 대체하는 Qualcomm의 WALT(Window Assisted Load Tracking)다. WALT는 10년 전 업스트림에 제출된 적이 있고 일부 아이디어는 PELT에 흡수됐다. 우선순위 역전 회피도 흔한 용도인데, 락 프리미티브를 손보거나 중요한 프로세스용 별도 런큐를 두는 식이다. 목표는 언제나 사용자 입력에 빠르게 반응하고 프레임 드롭 없이 화면을 그리는 것이다.

훅을 쓰는 가장 큰 이유는 급해서다. 지금 제품에 필요한 변경인데 업스트림 절차가 너무 느리다. 벤더들은 “좋은 의도”는 있지만 메인라인까지 가져갈 인내심은 부족하고, 업스트림 드라이버가 없는 하드웨어 지원도 이유다. Android 쪽은 모든 시스템을 이해하지 못해 어떤 변경이 정말 중요한지 판단할 수 없으므로 훅 추가 정책이 관대하다. 훅은 현재 약 800개이고 Android 개발자들도 줄이고 싶어 한다.

Corbet이 스케줄러 쪽 수정이 많으니 벤더를 sched_ext로 유도해 보면 어떠냐고 묻자, Kjos는 sched_ext가 이미 Android 커널에서 지원되지만 그 결과 sched_ext 인프라에도 벤더 훅이 붙었다고 씁쓸하게 답했다. 그러면서 완전히 out-of-tree인 스케줄러 구현으로 옮겨 가느니 벤더 훅으로 남는 게 낫다고 봤다. 같은 트랙 후반에는 Aiqun Yu가 실시간 태스크 스케줄링을 sched_ext로 옮겨 일부 훅을 없애는 작업을 발표했다. 훅 추가를 더 강하게 거절하면 되지 않느냐는 청중 질문에 Kjos는 판단할 전문성이 없다는 답을 반복했다.

댓글에서는 메인라인이 심볼 export에는 엄격한데 Android는 왜 벤더 훅에 관대하냐는 질문이 나왔다. 두 정책은 서로 다른 집단(코어 커널 개발자와 Google의 Android 커널 팀)이 정하고, 메인라인에는 벤더 훅 메커니즘 자체가 없다. 또 Android의 심볼 export 정책은 EXPORT_SYMBOL()에 더해 허용 목록(allowlist)까지 요구해 메인라인보다 오히려 더 엄격하다는 지적도 있었다.

재현 가능한 배포판을 위한 해시 기반 모듈 무결성

Linutronix의 Thomas Weißschuh가 LPC Build Systems 마이크로컨퍼런스에서 커널 모듈 무결성 보장과 재현 가능한 빌드(reproducible build)를 동시에 만족시키는 패치 세트를 소개했다. Reproducible Builds 프로젝트의 정의에서 핵심은 “비트 단위로 동일”과 “누구나”다. Debian은 이미 약 99% 재현 가능하고 곧 정책 매뉴얼에 재현성을 요구사항으로 넣을 예정이다.

문제는 지금의 모듈 서명 방식이다. 서명은 .ko 파일 끝에 붙고 커널은 이미지에 내장된 공개 키로 검증한다. 서명된 모듈을 재현하려면 개인 키도 공개돼야 하는데 그러면 공격자가 아무 모듈이나 서명할 수 있다. 흔한 방식은 빌드 때 키 쌍을 만들고 개인 키를 버리는 것인데, 안전하지만 나중에 재현할 수 없다. 배포판마다 선택이 다르다.

배포판방식우선한 것
Arch Linux빌드 후 폐기하는 임시 키로 서명보안
NixOS모듈 서명 없음재현성
Debian일부 모듈은 비공개 키로 서명, 재현 가능한 빌드에는 서명 없음둘 다(대신 패키징이 복잡)

해시 리스트에서 Merkle 트리로

첫 해법은 허용된 모듈의 해시 목록을 커널 이미지에 넣는 것이었다. 2024년 Reproducible Builds의 “kpcyrd”와 Weißschuh가 각자 떠올렸고, 10년 전 한 상용 리눅스 벤더 제품에도 들어간 적이 있다. 하지만 모듈 5,000개에 SHA-256 32바이트면 “커널에서 영영 사라지는 150KB”가 된다. 리뷰어 제안으로 Merkle 트리로 바꿨다.

항목Merkle 트리 방식
트리 구성리프는 각 모듈의 해시, 위로 갈수록 두 노드 해시를 다시 해시
모듈 “서명”리프 인덱스 + 루트까지 경로상의 형제 해시. .ko에 붙고 로드 후 버린다
메모리 상주루트 해시와 트리 깊이뿐. X.509 인증서나 해시 목록보다 작다
재현성해시 함수만 쓰므로 결정적
부수 효과런타임 X.509 처리와 빌드 시 OpenSSL 의존 제거 가능. 한 엔터프라이즈 배포판은 HSM으로 수천 개 모듈을 하나씩 서명하던 병목이 루트 하나 서명으로 줄었다

검증 가능한 내장 모듈이 생기면 그 위에 더 쌓을 수 있다. 커널과 함께 빌드된 모듈에는 modversions가 필요 없고, 일부 심볼 export를 트리에 있는 모듈로만 제한할 수 있으며, 지금은 모듈이 마음대로 위조할 수 있는 MODULE_INFO() 메타데이터도 신뢰할 수 있게 된다.

남은 과제는 Kbuild다. 지금 Kbuild는 커널 이미지를 먼저 빌드하고 BTF 같은 데이터를 뽑은 뒤 모듈을 빌드하는데, 이 방식은 모듈 해시를 이미지에 넣어야 하므로 모듈이 먼저 빌드돼야 한다. 패치는 #ifdef로 우회하고 있어 지저분하다. 또 strip은 보통 설치 시점에 하는데 strip하면 해시가 바뀌므로, 빌드 중에 strip해서 해시를 계산하고 패키징에는 strip 전 버전을 넘긴다. 두 strip 결과가 같다는 가정에 기대는 셈이라 본인도 만족스럽지 않다고 했다. Sashiko는 vmlinux와 modules 타깃을 한 번에 호출하면 경쟁 상태가 난다는 Kbuild 버그까지 찾아냈다. “Sashiko가 생기기 전에 제출했어야 했다”는 게 그의 농담이다. IMA와의 연동, fs-verity 등 다른 Merkle 트리 구현과 코드 공유 여부도 열린 질문이다.

반응은 좋다. lockdown을 만든 Matthew Garrett은 “lockdown은 내 잘못이고 이건 마음에 든다”며 지지했다. fs-verity·dm-verity 메인테이너 Eric Biggers도 기존 서명 처리 코드보다 훨씬 단순하다며 반겼지만, 모든 모듈을 커널과 함께 빌드해야 한다는 제약을 짚었다. Weißschuh는 나중에 빌드한 모듈로 별도 Merkle 트리를 만들어 부팅 시 넘기는 확장이 가능하다고 답했다. Biggers는 SHA-256 코드는 공유해야 하지만 트리마다 레이아웃과 용도가 달라 Merkle 트리 구현을 공유할 여지는 적다고 봤다. Weißschuh는 특히 crypto와 Kbuild 쪽 리뷰가 부족하다며 리뷰를 요청했다.

커널 Rust의 안전한 자기 참조 자료구조

자기 참조 구조체는 알고리즘적으로 우아한 선택일 때가 많지만 Rust 라이프타임 규칙으로는 unsafe 없이 구현하기가 사실상 불가능했다. Kangrejos 2026에서 Gary Guo가 커널의 pin_init 크레이트(C와의 상호운용을 위해 움직이지 않는 구조체를 만드는 도구)를 확장해 이 문제를 푸는 방법을 발표했다. 목표는 Nova 드라이버에서 라이프타임 관련 unsafe 코드를 대부분 없애는 것이다.

Devres에서 라이프타임으로

디바이스 자원은 디바이스가 바인딩돼 있는 동안만 접근할 수 있다. 원래 Rust 드라이버 바인딩은 내부에 Revocable 포인터를 둔 Devres 타입으로 이를 모델링해 접근할 때마다 디바이스가 살아 있는지 확인하게 했다. 드라이버가 이미 바인딩 상태를 아는데도 실패 가능한 경로가 드라이버 곳곳에 생겼고, 실패할 수 없는 Drop 안에서 디바이스에 접근해야 하는 패치가 나오자 한계가 드러났다. Guo는 이를 라이프타임으로 모델링해 컴파일러가 그 에러 경로가 불필요함을 증명하게 하려 했다.

먼저 보조 버스(auxiliary bus)의 타입 소거 문제를 풀었다. Any는 'static이 아닌 라이프타임을 담은 타입에 구현될 수 없으므로, 모든 라이프타임에 대해 well-formed한 고차(higher-rank) 타입을 요구하는 방식으로 바꿨다. Rust가 이를 직접 표현하지 못해 CovariantForLt!() 매크로로 우회한다. 그 결과 드라이버 구조체가 다음처럼 바뀐다.

// 이전
struct MyDriver {
    device: ARef<Device>,
    pci_bar: Arc<Devres<Bar<BAR_SIZE>>>,
}

// 이후
struct MyDriver<'bound> {
    device: &'bound Device,
    pci_bar: Arc<Bar<'bound, BAR_SIZE>>,
}

개념적으로 BAR는 Device와 수명이 같으니 Arc도 필요 없어야 한다. Nova는 이를 unsafe 코드로 처리하고 있었는데, gpu가 내부적으로 bar를 참조하므로 둘을 같은 라이프타임으로 선언하는 건 거짓말이기 때문이다. Guo의 패치 세트는 #[pin_data]가 구조체 필드 이름을 라이프타임으로 쓸 수 있게 해서 이 관계를 정확히 기록한다.

#[pin_data]
struct NovaCore<'bound> {
    reg: auxiliary::Registration<
        'gpu, ForLt!(NovaCoreApi<'_>)
    >,
    gpu: Gpu<'bar>,   // gpu는 bar 필드를 빌린다
    bar: Bar<'bound, BAR_SIZE>,
}

이 구조체는 일반 pin_init!() 호출로 초기화한다. 필드 직접 접근은 막히고, 매크로가 공변(covariant) 필드에는 foo(), 불변(invariant) 필드에는 콜백 기반의 with_foo(), 여러 필드를 동시에 다룰 때는 project()/with_project()를 생성한다. moveit, rental, yoke, ouroboros 같은 기존 크레이트는 암묵적 할당을 가정하거나 아예 건전하지(sound) 않아 커널에 쓸 수 없었다.

건전성을 위한 긴 여정

문법 자체보다 건전성 확보가 훨씬 어려웠다. Guo는 가장 단순한 예제로 잘못된 매크로 구현들을 하나씩 짚었다.

시도/함정왜 안 되나해법
&'owner를 &'static으로 바꾸고 접근 시 검사사용자 코드가 필드에 직접 접근해 라이프타임을 어길 수 있다비공개 래퍼 Erase로 감싼다
단순 래퍼auto trait(Send 등)이 'static을 보고 잘못 추론한다함수 타입의 고차 다형성을 재귀적으로 이용한 래퍼. 불안정 기능 unsafe binders가 안정화되면 unsafe<'owner> &'owner String으로 대체 가능
drop 순서Rust는 선언 순서대로 필드를 drop하므로 소유자가 먼저면 댕글링 참조가 생긴다필드는 뒤쪽 필드만 참조하도록 검사
&'later_owner &'owner () 같은 병적 필드구조체 정의의 참조는 well-formed라고 가정되므로 잘못된 라이프타임 관계가 통과한다호출되지 않는 함수를 생성해 drop 순서대로 지역 변수를 선언, 함수 본문에서는 well-formedness가 검사된다는 점을 이용

Guo는 “자기 참조 라이브러리 중 가장 철저한 방어”라고 자신했지만, Danilo Krummrich가 Nova에 적용하다 막혔다. GSP 커맨드 큐를 Mutex로 감싸면 필드가 라이프타임에 대해 불변이 되고, 그 불변성이 최상위 NovaCore까지 전파돼 보조 디바이스 등록과 충돌한다. 우회책으로 찾은 코드는 알고 보니 건전하지 않았다. Guo는 형식적 타입 추론 규칙 슬라이드(청중이 웃음을 터뜨렸다)를 꺼내 존재 라이프타임(existential lifetime)으로 원인을 설명했다. 소거된 비공변 라이프타임이 하한(lower bound)으로 걸린 라이프타임은 공변으로 취급하면 안 된다는 규칙이다. 결국 매크로에 exists 바인딩 문법을 추가해 상한(upper bound)으로만 쓰이는 라이프타임을 안전하게 도입하게 했다.

#[pin_data]
pub(crate) struct CommandQueue<'a>
where
    exists<'cmdq>: 'a,
{
    #[pin]
    #[not_covariant]
    inner: Mutex<CommandQueueInner<'cmdq>>,
}

이것으로 debugfs 코드를 빼면 Nova의 라이프타임 관련 unsafe 코드를 모두 제거할 수 있다. 사용자는 대부분 필드 이름을 라이프타임으로 쓰는 것만 알면 되고, 순서를 잘못 쓰면 매크로가 설명 메시지를 낸다. 원래 일부만 먼저 올릴 계획이었으나 컨퍼런스 후 논의를 거쳐 전체를 한 시리즈로 올렸다. 다만 발표가 끝날 무렵 청중 상당수가 얼떨떨한 표정이었고, pin_init 리뷰어 입장에서는 결코 단순하지 않아 적절한 리뷰를 받을 수 있을지는 지켜봐야 한다.

리눅스 NFS 서버의 최근 변화와 앞으로

NFS 개발자 Jeff Layton이 LPC에서 리눅스 NFS 서버에 최근 들어간 기능과 곧 올 변화를 빠르게 훑었다. 주요 내용은 다음과 같다.

기능내용
LOCALIO컨테이너 환경 등에서 클라이언트와 서버가 같은 호스트에 있으면 프로토콜 처리를 건너뛰고 파일시스템으로 직행
비동기 서버 측 복사같은 서버 또는 제3 서버로의 복사를 클라이언트를 거치지 않고 비동기로. 명세 문제를 먼저 고쳐야 했다. 기본 활성화
uncached I/O클라이언트가 공격적으로 캐싱해 서버 페이지 캐시 적중률이 낮으니 direct I/O나 캐시 비활성 요청 사용. 지금은 서버 옵션, 곧 exports/exportfs 옵션으로
한계 상향과 락 분할RPC 프레임 4MB, 버퍼 8MB, 동적 스레드 풀(기본 꺼짐). “1990년대엔 괜찮았던” 전역 뮤텍스를 연결별 뮤텍스로 분할
멀티 그레인 타임스탬프모든 파일 변경이 관찰 가능한 타임스탬프 변화를 만들어 캐시 무효화를 정확하게. Btrfs, ext4, XFS, tmpfs 지원
속성 위임(RFC 9754)클라이언트가 타임스탬프와 파일 크기를 관리. “타임스탬프가 얽힌 건 전부 까다롭다”
쓰기·디렉터리 위임쓰기 전용 open에도 쓰기 위임. 디렉터리 위임은 위임을 회수하는 대신 증분 업데이트 전송. 커널 빌드라는 “유일하게 중요한 벤치마크”가 빨라진다
동적 세션 크기 조정워크로드와 서버 자원에 따라 클라이언트별 슬롯 수 조절
NFSv4.2 POSIX ACL실패한 Windows식 ACL 모델 대신 POSIX ACL을 직접 주고받음
서명된 파일 핸들핸들 추측 공격 방어. 스니핑은 여전히 가능하니 TLS와 함께 쓰면 “꽤 안전”
case folding, re-export서버 파일시스템의 대소문자 무시 동작을 클라이언트에 노출. NFS를 다시 export하는 캐싱 프록시(AWS, Google Cloud에서 사용)
netlink 관리 APInfs-utils의 nfsdctl. 새 기능은 netlink로만 제어하고 /proc/fs/nfsd는 폐기 예정. mountd도 netlink로 이전
xdrgen손으로 쓰던 XDR 코드를 자동 생성. 지금은 C를 생성하지만 공격 표면이 큰 Sun RPC 계층을 위해 언젠가 Rust로

NFS 메인테이너들도 품질이 들쭉날쭉한 패치 홍수를 겪고 있다. 네트워크에 노출된 서버라 취약점 리포트를 최대한 처리했고 “최악 중의 최악”은 업스트림에서 이미 고쳤다. 앞으로는 pNFS SCSI 레이아웃 강화, xdrgen과 netlink 확대, 인증서로 파일시스템 접근을 제한하는 “TLS session tagging”이 예정돼 있다. NFSv2 지원은 제거된다. 쓸 이유가 없고 배포판이 끄기만 기다리는 상태다. VFS 수준에서 지금은 직렬화된 디렉터리 변경 연산을 병렬화하는 작업도 진행 중이다.

SUSE의 시스템 전역 setuid 비활성화

SUSE 보안팀은 이미 리뷰·승인받지 않은 setuid/setgid 바이너리를 패키지에 넣지 못하게 한다. SUSE의 distinguished engineer Thorsten Kukuk은 All Systems Go! 2026에서 한 걸음 더 나아가 아예 막는 작업을 발표했다. 방법은 systemd PID 1 자체에 NoNewPrivileges=yes를 걸어 모든 프로세스에 커널 no_new_privs 플래그를 켜는 것이다.

[Manager]
NoNewPrivileges=yes

no_new_privs가 켜지면 setuid·setgid·파일 capability 바이너리를 execve()해도 권한이 올라가지 않고, 이 설정은 execve(), clone(), fork()를 거쳐 상속된다. 이미 권한이 있는 태스크가 setuid()/setresuid()를 직접 호출하는 것은 막지 않는다. Copy Fail 공개 때 Kukuk이 배포판 무관 범용 익스플로잇들을 이 설정을 켠 시스템에 돌려 봤더니 “하나도 통하지 않았다”. LLM 이전이라면 “모든 스크립트 키디를 막았을 것”이라고 하겠지만, 이제는 LLM으로 시스템별 맞춤 공격을 만들 수 있어 전부 막지는 못할 것이라고 했다.

그는 account-utils에 포함된 scan-caps로 setuid/setgid/capability가 붙은 바이너리를 찾았고, 사용자 입장에서 대부분의 도구가 변경 없이 동작하도록 대체재를 만들었다. sudo를 run0로 바꾸면 sudoers 대신 polkit 규칙을 써야 하는 것처럼 동작이 바뀌는 “침습적 패키지”는 소수다.

영역기존(setuid 필요)대체
계정 관리shadow-utils(passwd, chsh, chage), PAM unix, MariaDB 인증 등이 /etc/shadow 직접 읽기varlink로 통신하는 샌드박스된 systemd 서비스 pwaccessd/pwupdd와 소형 클라이언트 바이너리, PAM 모듈 pam_unix_ng.so. 설정은 pwaccessd.conf 한 곳
권한 상승su, sudo, pkexecrun0와 이 세 명령의 주요 옵션을 지원하는 래퍼
FUSEsetuid root인 fusermount3setuid 없는 구현 defused
Postfixsetgid인 postdrop, postlog, postqueue업스트림에서 “postdmux” systemd 서비스 작업 중(시점 미정)

run0의 걸림돌은 터미널에서 실행해도 KDE나 GNOME 인증 대화상자가 뜬다는 점이다. 이를 악성코드로 오인한 버그 리포트도 들어왔다. 컨테이너 40개를 살펴보니 su는 권한을 내릴 때만 쓰였지만 sudo는 아예 동작하지 않았다. Distrobox처럼 컨테이너 안에서 sudo로 root가 되는 사용 패턴은 바깥에서 podman exec/docker exec를 쓰는 것으로 우회한다. rootless 컨테이너는 Podman에서는 되지만 Docker는 RootlessKit의 권한 처리 버그로 안 된다. SELinux 정책은 대부분 조정됐으나 run0 정책은 미완성이라, SELinux를 켜면 run0로 chown, passwd, 로컬 스크립트를 실행할 수 없다.

Kukuk은 Pi-hole DNS 서버를 빼고 자신의 openSUSE Tumbleweed·MicroOS 시스템 전부에서 이 설정을 쓰고 있고, KDE 데스크톱에서도 필요한 앱은 다 돌아간다고 했다. MicroOS는 신규 설치에 이미 account-utils를 쓰고, Tumbleweed도 신규 설치 기본값으로 만들 계획이다. AppArmor와의 조합은 “큰 문제가 있다”고 들었을 뿐 사내에 AppArmor 전문가가 없어 확인하지 못했고, Canonical이 가장 잘 볼 수 있을 것이라고 했다.

XArray를 Rust로 다시 쓰는 논의

출발점은 XFS다. XFS는 2021년 12월 large folio를 지원했는데, 2023년 6월 한 파일의 페이지가 다른 파일에 섞이는 데이터 오염이 보고됐다. 원인은 락 없이 트리 연산을 하는 XArray API 오용이었고 버그는 몇 년간 아무도 모른 채 남아 있었다. 사용자 상당수가 안정 커널만 쓰기 때문일 수 있다. folio 지원을 되돌리느라 XFS의 큰 블록 크기 지원도 멈췄다. Daniel Gomez는 Kangrejos에서 Rust 구현이었다면 이 버그가 애초에 들어오지 않았을지 물었다.

XArray는 “배열인 척하는 radix 트리”다. xa_*() 단순 API는 읽기에 RCU, 쓰기에 내부 스핀락을 쓰고, xas_*() 고급 API는 트리 안의 커서처럼 동작하며 락을 사용자에게 맡긴다. 고급 API는 주로 페이지 캐시와 XFS 같은 일부 파일시스템이 쓴다. 사용처는 351곳, MAINTAINERS 항목 126개에 걸쳐 있고 2026년에만 XArray 오용으로 CVE가 3건 나왔다. Kent Overstreet은 애초에 maple 트리가 맞는 자료구조라고 했지만, XArray에는 maple 트리에 없는 기능이 많다.

구현상 걸림돌상황
슬롯 포인터 태깅컴파일러가 자동으로 못 해서 수작업 구현. Rust 프로젝트가 작업 중
꼬리 호출 최적화Rust가 C에 없던 Drop::drop() 호출을 끼워 넣어 LLVM이 재귀를 루프로 못 바꿈. 코드 구조 변경으로 우회, #[must_tail]이 있었으면 쉬웠을 것
노드 크기 가변const generics가 불안정 기능이라 Benno Lossin 제안대로 매크로로 생성

직접 만든 자료구조 벤치마크에서 Rust 버전은 C보다 “약간 빠르다”. 다만 덜 쓰이는 기능이 다 구현되지 않아 단정하지는 않았다. 더 중요한 건 런타임에 올바른 사용을 검증하는 안전한 인터페이스다.

Miguel Ojeda는 Rust 사용자가 있으면 Rust 구현을 추가하는 건 정당화하기 쉽지만, C 호출자용 C API를 제공하는 건 Greg Kroah-Hartman이 보통 받지 않는다고 했다. 현실적으로는 커널이 지원하는 모든 아키텍처에서 Rust가 돌아야 핵심 기능을 대체할 수 있다. Matthew Wilcox도 같은 이유로 시기상조라고 했었다. Daniel Almeida는 Arm Mali용 Tyr 드라이버의 잡 큐가 첫 Rust 사용자가 될 수 있다고 했다. Alistair Francis가 C 호출자는 여전히 오용할 수 있지 않냐고 묻자 Gomez는 안전 요구사항을 타입에 명시한 API는 C 사용자에게도 도움이 된다고 답했다. Andreas Hindborg는 Rust 타입을 C에서 쓸 때의 확인 목록을 문서에 자동으로 넣어 방어 코드를 줄이자고 제안했고, 현재 XArray 문서에 안전한 사용 조건이 없는 것도 오용의 원인일 수 있다고 짚었다.

Josh Triplett은 보안보다 성능으로 설득하라고 조언했다. “50~70% 빠르다는 걸 보여주면 반박하기 어렵다.” Rust의 noalias 정보가 도움이 되느냐는 질문에 Gary Guo는 C 상호운용 때문에 UnsafeCell로 표시된 타입이 많아 커널에서는 효과가 적다고 했다. 남은 일은 트리 축소(지금은 커지기만 한다), entry·preload·RCU API다. Gomez는 컨퍼런스 후 패치 세트를 공개하고 7.4 포함을 요청했다. 아직 완성되지 않아 XArray 사용자가 바로 옮겨 탈 단계는 아니다.

Rust의 크레이트 간 전방 선언

커널 Rust 코드는 디버그·릴리스 빌드 모두 정수 오버플로 시 panic한다. 처음부터 오버플로를 몰아내려는 결정이었지만, 토발즈는 예상치 못한 오버플로로 커널 전체가 죽어선 안 된다는 입장이다. 커스텀 panic 핸들러에서 WARN()을 찍고 계속하면 될 것 같지만, Rust는 panic 핸들러를 반환하지 않는 함수로 정의하고 그 가정이 언어 깊숙이 박혀 있다.

Rust 컴파일러 기여자 Jana Dönszelmann은 이 문제를 더 일반적인 시각에서 봤다. panic 핸들러, 커스텀 할당자, 디버그 로깅은 표준 라이브러리가 “어딘가에 정의될 함수”를 전방 선언하는 세 가지 특수 사례다. 이를 “externally implementable items”(임시 이름)라는 언어 기능으로 일반화했고, nightly에서 쓸 수 있다.

상황#[eii] 함수의 동작
선언한 크레이트에 본문이 있고 다른 정의 없음그 본문을 폴백으로 사용
다른 크레이트 하나가 정의그 정의를 사용, 폴백 무시
두 크레이트가 정의컴파일 에러
폴백도 정의도 없음컴파일 에러

검사는 컴파일러가 크레이트 그래프 전체를 보고 하지만, 구현은 weak 링킹이라 크레이트별 병렬 코드 생성이 유지된다. Windows에서는 weak 링킹이 까다로워 지금은 유닉스 계열만 지원한다. 그 위에 새 플래그 -Coverflow-checks=report를 켜면 오버플로 시 report_integer_overflow()가 호출되는데, 반환 가능한 보통 함수라 이후 코드가 죽은 코드로 취급되지 않는다. 기본 구현은 기존 panic 핸들러를 부르므로 커널은 플래그와 자체 핸들러를 둘 다 넣어야 한다.

Ojeda는 플래그를 커널에 넣을 가치가 있고, 토발즈가 밀어붙일 수도 있는 “조용히 오버플로 허용”보다 낫다고 봤다. Alice Ryhl이 weak 심볼 덮어쓰기 문제를 걱정하자 Kroah-Hartman은 커널에 weak 심볼이 흔하다고 했고, Dönszelmann은 컴파일러가 정의가 하나뿐임을 보장한다고 답했다. Guo는 인라인 여부를 물었는데 지금은 안 되지만 원칙적으로 가능하고, WARN() 호출은 어차피 콜드 경로라 상관없다는 데 의견이 모였다. Triplett은 커널 전체 대신 현재 커널 스레드만 멈추자고 했지만, Guo는 스레드 스택이 누수되지 않고 해제되므로 Rust 코드에서 커널 스레드가 죽는 것은 건전하지 않다고 지적했다.

Nix flakes 이해하기

Nix flakes는 Nix 패키지 관리자의 실험적 기능이지만, 업스트림 NixOS 패키지가 없는 프로젝트도 flake.nix로 개발 환경과 빌드 자동화를 제공할 만큼 널리 퍼졌다. Debian 13과 Fedora 45 사용자가 서로 다른 툴체인 버전을 갖는 문제를, 의존성을 고정한 flake 하나로 해결한다는 것이 핵심이다. NixOS 없이 Nix만 있어도 쓸 수 있다.

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
  };

  outputs = { nixpkgs, ... }: {
    packages.x86_64-linux.hello =
      nixpkgs.legacyPackages.x86_64-linux.hello;
  };
}

nix flake lock은 Cargo.lock처럼 각 input을 특정 커밋에 고정하는 flake.lock을 만든다. legacyPackages는 레거시라는 뜻이 아니라 nix flake show가 10만 개 넘는 패키지를 출력하지 않게 하는 호환용 이름이다. flake는 순수 평가(pure evaluation) 모드로 평가돼 환경 변수를 읽을 수 없고 네트워크 접근은 체크섬으로 검증된다(--impure로 완화 가능).

# ~/.config/nix/nix.conf 또는 /etc/nix/nix.conf
# experimental-features = nix-command flakes

nix flake show github:ghostty-org/ghostty     # 저장소가 제공하는 outputs 확인
nix develop github:ghostty-org/ghostty        # zig 툴체인이 갖춰진 개발 셸 진입
nix develop github:niri-wm/niri --command rustc --version

개발 셸의 툴체인은 Nix 스토어의 별도 경로에 설치되므로 같은 툴체인의 여러 버전이 충돌 없이 공존한다. 기사 예시에서는 Ghostty 셸에서 zig 0.16.0, niri에서 rustc 1.97.0, pandoc에서 GHC 9.10.3이 호스트에 아무것도 설치하지 않은 상태로 제공됐다.

문제는 역사다. Eelco Dolstra가 2019년 7월 RFC 49로 제안했지만 합의에 실패해 2020년 7월 철회됐고, flakes는 2021년 Nix 2.4에 실험적 기능으로 들어갔다. 그런데도 2025 NixOS 커뮤니티 설문(약 3,400명)에서 78.9%가 flakes를 쓴다고 답했다. 기능을 원하는 쪽은 실험 딱지에 답답해하고, 원래 RFC 참여자 일부는 범위와 설계가 실험의 한도를 넘어섰다고 불만이다. 이 균열은 구현체 간 차별점이 됐다.

구현체flakes 입장
Nix(CppNix)실험적. RFC 136(2023년 8월 승인)으로 새 CLI와 flakes를 점진 안정화 중, 완료 시점 미정
Lix동결(frozen), 향후 플러그인으로 분리 예정
Determinate Nix안정 기능, 기본 활성화

안정화까지는 lock 속성 변경 같은 호환성 깨짐과, 불필요한 스토어 복사를 없애는 “lazy trees” 같은 성능 개선이 남아 있다. 새 nix CLI 설계가 먼저 안정화돼야 하고 flakes 최종 설계를 위한 RFC도 하나 더 필요하다. RFC 136은 순수 평가처럼 flakes 없이도 가능해야 할 기능이 flakes에 묶여 버렸다는 비판을 인정하면서도, 단계적으로 가면 모두를 만족시킬 수 있다고 낙관한다.

짧은 소식

  • eMudhra 중간 CA 키 유출 — eMudhra 중간 인증서 8개의 개인 키가 유출됐다는 보고를 받고 Mozilla가 OneCRL로 차단하고 NSS 3.131.1에서 신뢰 목록을 갱신했다. 공격자가 남의 사이트용 HTTPS 인증서를 발급해 트래픽을 가로챌 수 있는 키다. Chrome은 10월 17일, Apple은 19일, Microsoft는 20일 차단했고 NetBSD도 차단 방법을 공지했다. 다른 OS나 클라이언트 사용자는 업데이트를 확인할 것.
  • PHP 원격 코드 실행 취약점 2건 — PHP 8.5.12, 8.4.27, 8.3.36, 8.2.35가 인증 없는 RCE 두 건을 고쳤다. OOM 처리 중 부분 초기화된 요청 데이터를 정리 단계가 유효하다고 착각하는 CVE-2026-109618, 해제된 메모리를 가리키는 요청 상태가 같은 워커의 다음 요청에서 쓰이는 CVE-2026-109619다. PHP-FPM, mod_php, php-cgi, FrankenPHP, LiteSpeed 모두 해당되고, 애플리케이션 코드 실행 전에 공격이 가능한 익스플로잇이 시연된 mod_php가 가장 위험하다. 8.1 미만은 업데이트가 없지만 7.4~8.1용 백포트 참고 패치가 제공됐다. PHP Foundation은 경쟁하는 수정안 사이에서 합의 기반 의사결정이 몇 달간 멈췄고 자원도 부족했다며 “구조적 실패”였다고 인정했다.
  • Node.js·musl 취약점 — Node.js는 Brotli 압축을 쓰는 프로그램의 RCE를 포함한 보안 업데이트를 냈다. musl libc도 RCE로 이어질 수 있는 범위 밖 쓰기(out-of-bounds write) 취약점을 발표했다(RCE는 아직 시연되지 않음).
  • 커널 7.3 릴리스 — 10월 18일 릴리스. 토발즈는 연례 가족 휴가 중이라 7.4 머지 창 첫날은 “보트 위와 물속”에서 보내고 오후에 머지를 시작한다고 했다. 주요 변경은 binfmt_misc 확장, 대형 시스템용 그룹 스케줄링 개선, 모든 연산이 실패하는 failfs, fchroot() 시스템 콜, BPF용 전역 per-CPU 데이터, sched_ext 서브스케줄러 완성, VM 워킹셋 추적, ntfs3 대체 데이터 스트림(ADS), SMB 서버 개선 등이다. rc2 이후 주당 커밋은 681 → 733 → 598 → 649 → 596 → 447 → 289건이었다. 안정 업데이트는 10월 15일 7.2.11, 6.18.57, 6.12.113, 6.6.159, 6.1.190, 5.15.223, 5.10.272, 21일 7.2.12, 6.18.58, 6.12.114, 6.6.160이 나왔다.
  • Tyr 업스트림 현황 — Collabora가 Arm Mali GPU용 Rust 드라이버 Tyr 소식을 전했다. Rust 커널 추상화가 함께 개발되는 중이라 인터페이스가 바뀔 때마다 Tyr를 여러 번 다시 썼고, 잡 스케줄링 같은 기능은 추상화가 설계·머지될 때까지 멈춰 있다. 대신 새 추상화의 첫 사용자로서 요구사항과 한계를 드러내는 역할을 한다.
  • 이번 주 인용문: Sashiko 재전송 홍수 — Jiri Kosina는 하루 만에 v1부터 v11까지 패치 세트를 받았다며, 사람 리뷰 없이 Sashiko 피드백만으로 재전송이 이어지는 건 지속 불가능하다고 했다. Alexei Starovoitov는 반대로 “스팸을 계속 보내라”며, 에이전트가 받은편지함을 감시해 이전 버전을 보관하고 논의를 요약하게 한 뒤 봇들이 서로 대화를 멈출 때까지 기다렸다 사람의 몫을 하면 된다고 했다. Lyude Paul은 LLM이 Rust나 정적 분석기와 달리 프로젝트의 사회적 계약 자체를 바꿨다고 했고, Laurent Pinchart는 메인테이너 서밋 이후 여러 개발자가 “LLM을 안 쓰면 무시당하니 이직해야 하냐”고 물어왔다며 메인테이너들이 공개적으로 해명해 달라고 했다.
  • GNOME OS Preview — 개발자용 Nightly만 있던 GNOME OS에 안정 릴리스(GNOME 51.1) 기반의 Preview가 나왔다. 비개발자 애호가를 위한 것이지만 아직 일반 대중용 완성품은 아니며, 정식 버전이 나오면 재설치가 필요할 수 있다.
  • OpenBSD 8.0 — arm64 하이버네이트 지원, amd64 커널 가상 주소 공간 512GB로 확대, Qualcomm Wi-Fi 6용 qwx 드라이버 개선 등이 들어갔다.
  • Ubuntu 26.10 “Stonking Stingray” — Rust 기반 uutils coreutils 전환을 완료했고 Microsoft Entra ID 인증 연동을 강화했다. GNOME 51을 탑재했고 App Center의 snap/deb 관리 경험을 통일했다. 이전 버전과의 비호환 변경은 릴리스 노트를 확인할 것.
  • KDE 다큐멘터리 — 30주년을 맞아 “The KDE Documentary — A Story of Free Software Underdogs”를 공개했다. 1996년 Matthias Ettrich의 Usenet 글부터 Qt 라이선스 분쟁과 GNOME과의 경쟁, WebKit과 Chrome의 기반이 된 KHTML, KDE 4의 논란과 재건까지 다룬다.
  • LPC 2026 영상 공개, TAB 선거 결과 — 10월 5~7일 프라하 LPC 발표 영상이 YouTube 재생목록으로 공개됐다. Linux Foundation 기술 자문 위원회(TAB) 선거에서는 Kees Cook, Dave Hansen, Miguel Ojeda, Shuah Khan이 재선됐고 Laurent Pinchart가 새로 합류한다.

보안 인용문으로는 Seth Larson이 PyPI가 더 이상 인증서 배포 채널이어선 안 된다며, certifi 같은 패키지 대신 시스템 인증서 저장소에 기대고 OpenSSL 기반 플랫폼의 인증서 폐기 문제는 배포판 쪽 작업에 맡기자고 제안했다. eMudhra 사건과 맞물린 문제 제기다.

행사는 10월 30일~11월 1일 베를린 Qubes OS Summit, 11월 3~4일 Open vSwitch and OVN 가을 컨퍼런스, 6~7일 Texas Linux Festival, 7~8일 OpenFest(소피아)와 OpenALT(브르노), 12~13일 온라인 Ubuntu Summit 26.10, 14~15일 Capitole du Libre(툴루즈), 17~19일 Open Source Monitoring Conference(뉘른베르크), 20~21일 OLF Conference(콜럼버스)가 이어진다. 11월 28일에는 서울에서 FOSS for All Conference 2026이 열리고, 12월 1~3일 Yocto Project Virtual Summit 2026.12, 7~9일 Open Source Summit Japan(도쿄)이 있다. CFP 마감은 Yocto Project Virtual Summit이 10월 26일, Southern California Linux Expo가 11월 1일, AlpOSS 2027이 11월 2일, OpenEmbedded Workshop 2027이 12월 20일이다.

이번 주 핵심 요약

  • 7.3 통계는 지난주 메인테이너 서밋 논의의 숫자판이다. 개발자 4명 중 1명 이상이 처음 보는 사람이고, 버그 리포트의 절반이 자동화 시스템에서 온다. 동시에 같은 주기 안에서 고쳐지는 버그 비율이 7.1부터 떨어지고 있다는 건 자동 리뷰가 적어도 “바로 드러나는 버그”는 걸러내고 있다는 첫 정량 근거다. 7.3이 LTS가 될 예정이니 이 커널을 기반으로 제품을 만드는 쪽은 7.3.y 안정 업데이트의 수정 패치 양을 지켜볼 만하다.
  • Kosina와 Starovoitov의 인용문은 같은 현상에 대한 정반대 대응이다. 패치를 보내는 쪽이라면 Sashiko 지적이 올 때마다 바로 vN+1을 보내지 말고 사람 리뷰를 기다리는 편이 낫다. 지난주부터 반복되는 이야기지만 이번 주 v1→v11 사례로 더 구체적인 경고가 됐다.
  • Android 벤더 훅 이야기는 지난주 LTTng 기사와 같은 질문을 반대편에서 본다. 메인라인은 out-of-tree 코드를 위한 export를 막는데, Android는 훅 800개를 열어 두고 sched_ext에까지 훅을 붙였다. Android 커널에서 일한다면 스케줄러·메모리 관리 쪽 동작이 메인라인과 다를 수 있다는 전제를 깔고 성능 분석을 시작해야 한다.
  • Merkle 트리 모듈 서명은 “보안이냐 재현성이냐”를 고르던 배포판에게 둘 다 갖는 길을 연다. 자체 커널을 빌드해 서명하는 임베디드·엔터프라이즈 환경이라면 HSM 서명 병목이 루트 하나로 줄어드는 효과도 크다. 단, 나중에 빌드하는 out-of-tree 모듈은 이 체계 밖이라는 점을 설계에 넣어야 한다.
  • SUSE의 NoNewPrivileges=yes 실험은 지금 당장 따라 해볼 수 있다. 서버에서 find / -perm /6000 -type f와 getcap -r /로 setuid/capability 바이너리를 먼저 파악하고, sudo·su·fusermount3·Postfix setgid 바이너리 의존을 정리하는 것이 출발점이다. SELinux에서는 run0 정책이 미완성이고 AppArmor와의 조합은 검증되지 않았다는 점을 기억할 것.
  • Kangrejos 세 기사는 Rust for Linux가 드라이버 가장자리에서 코어로 다가가며 부딪히는 벽을 보여준다. 자기 참조 구조체는 언어에 없는 존재 타입을 매크로로 흉내 내야 했고, XArray는 아키텍처 지원과 C API 정책에 막혀 있고, 오버플로 처리는 컴파일러에 새 기능을 넣어야 풀린다. -Coverflow-checks=report가 들어오면 Rust 커널 코드의 오버플로가 C처럼 WARN() 후 계속하는 쪽으로 바뀔 가능성이 크다.
  • NFS 서버를 운영한다면 /proc/fs/nfsd 대신 nfsdctl(netlink)로 관리 스크립트를 옮길 시점이다. 새 기능은 netlink로만 제어된다. NFSv2가 아직 켜져 있다면 끄고, 대량 데이터를 서빙하는 서버는 uncached I/O 옵션이 exports로 나오면 페이지 캐시 오염을 줄이는 데 써볼 만하다.
  • Nix flakes는 “실험적”이라는 딱지와 달리 사실상 표준이 됐다. 팀 개발 환경을 맞추는 용도라면 flake.nix의 devShells와 flake.lock만으로도 충분히 가치가 있다. 다만 CppNix·Lix·Determinate Nix가 flakes를 서로 다르게 취급하니 어떤 구현체를 표준으로 삼을지 먼저 정해야 한다.
  • PHP RCE 패치는 이번 주 가장 급한 운영 이슈다. mod_php는 애플리케이션 코드 실행 전에 공격이 가능하므로 8.2~8.5 사용자는 즉시 업데이트하고, 8.1 이하는 배포판 백포트를 확인할 것. eMudhra 인증서 차단 여부도 브라우저 외 클라이언트(언어 런타임 번들 CA 등)까지 점검하는 편이 안전하다.

원문: LWN.net Weekly Edition for October 22, 2026

답글 남기기