LWN Weekly Report: 2026년 7월 9일 주요 뉴스

이번 주 LWN.net 위클리 에디션 주요 내용이다. 커널 crypto/CRC API를 라이브러리 형태로 재편 중인 작업, 파일시스템 iomap 계층 해설, LSFMM+BPF 서밋 후속 세션(negative dentry 제한, 더 빠른 RCU와 락 없는 메모리 할당), 유명 커널 개발자 두 명이 제출한 LLM 지원 패치 시리즈가 정반대 반응을 얻은 사례, 그리고 Guix 취약점·OpenSSH 10.4·kernel.org 인시던트까지 다룬다.

커널 암호화 라이브러리화 진행 상황

2026 Linux Security Summit North America(LSS NA)에서 crypto/CRC 라이브러리 및 fscrypt/fs-verity 메인테이너 Eric Biggers가 커널 암호화 API 현대화 작업을 발표했다. 2002년부터 있던 전통 crypto API는 복잡하고 느리다는 지적을 받아왔다. HMAC-SHA256 계산 하나만 해도 crypto_alloc_shash()로 객체를 동적 할당하고, 에러를 매번 확인하고, SHASH_DESC_ON_STACK()으로 디스크립터를 스택에 잡는 등 절차가 번거롭다. 알고리즘이 이름으로 로드되는 구조라 CRYPTO_HMAC/CRYPTO_SHA256 Kconfig를 빠뜨려도 빌드는 되고 런타임에만 실패하며, 커널 초기화 이전 시점(early init)에서는 아예 쓸 수 없다. 6.12 커널 기준 벤치마크에서는 HMAC-SHA256 연산 시간의 62%가 순수 API 오버헤드였다.

Biggers가 이끄는 새 라이브러리 API는 이 과정을 함수 하나로 줄인다.

hmac_sha256_usingrawkey(key, key_len, data, data_len, out);

6.17 커널에 추가된 이 함수는 항상 성공하고(에러 처리 불필요), 모든 컨텍스트에서 동작하며, 이름이 아닌 링크 타임 의존성을 쓰기 때문에 런타임 실패가 없다. 속도는 앞서 언급한 방식보다 약 2.5배 빠르다. ChaCha20-Poly1305 같은 AEAD 알고리즘도 마찬가지다. 전통 API로는 scatter-gather list를 직접 구성하고 비동기 완료 처리(잘못하면 use-after-free)까지 신경 써야 하지만, 라이브러리 API는 chacha20poly1305_encrypt(dst, src, src_len, ad, ad_len, nonce, key) 한 줄로 끝난다(이 함수 자체는 WireGuard 지원을 위해 2019년에 이미 추가됐다).

7.1 커널 기준으로 지원 알고리즘의 절반 가까이가 최근 1.5년 사이 추가됐고, apparmor·btrfs·dm-verity·fscrypt·bluetooth 등 다수의 커널 코드가 이미 라이브러리 방식으로 전환됐다. 전통 API로는 표현이 까다로웠던 SHAKE128/SHAKE256 같은 가변 길이 출력(XOF) 함수, ML-DSA 서명 검증도 새로 추가됐다. 성능 개선 사례도 인상적인데, arm64/RISC-V/x86_64용 CRC 최적화 중 한 건은 최신 AMD 프로세서의 16K 메시지 CRC64 처리량을 12,400% 끌어올렸다. 7.1 커널에는 KUnit 테스트 스위트도 crypto용 18개, CRC용 1개가 새로 추가돼 KernelCI 등 CI 파이프라인에 바로 통합됐다.

Biggers는 “가능하면 항상 라이브러리 함수를 쓰라”고 권한다. 예외는 두 가지뿐이다. 라이브러리에 아직 없는 기능(AES-GCM 등, 현재 작업 중)을 쓰는 경우와, 사용자 공간이 임의의 알고리즘 이름을 지정할 수 있어야 하는 기능(하위 호환성 때문에 전통 API 유지 필요)이다. 그는 새 커널 기능을 만들 때 사용자 공간이 임의 문자열로 아무 알고리즘이나 고를 수 있게 여는 방식을 “사용자를 위한 대형 지뢰”라고 부르며, MD5·MD4 같은 이미 취약한 알고리즘까지 선택 가능해지는 문제를 지적했다.

iomap 계층 이해하기

파일시스템 구현 이야기에는 “iomap”이라는 계층이 자주 등장하지만 정작 이게 뭔지 정확히 아는 사람은 많지 않다. iomap은 파일 공간(파일과 오프셋)과 스토리지 공간(메모리 위치 또는 디스크 블록) 사이의 매핑을 처리하는 계층으로, Christoph Hellwig가 Dave Chinner의 XFS 구현을 바탕으로 4.8 커널(2016년)에 도입했다. 현재는 fs/iomap 디렉터리의 파일 12개로 구성되며, 저수준 매핑 계층과 그 위에서 파일시스템 기능 대부분을 구현하는 고수준 계층 두 겹으로 나뉜다.

과거에는 이 매핑을 buffer head가 담당했는데, 디스크 블록과 메모리 영역을 1:1로 연결하는 구조라 대용량 파일이나 extent 기반 파일시스템에 맞지 않았다. 디스크의 연속된 extent 하나가 블록 하나씩만 관리하는 buffer head 수백 개로 쪼개지고, 이를 다시 소수의 I/O 연산으로 조립해야 했다. iomap은 이를 struct iomap 하나로 표현한다.

struct iomap {
	u64			addr; 		/* disk offset of mapping, bytes */
	loff_t			offset;		/* file offset of mapping, bytes */
	u64			length;		/* length of mapping, bytes */
	u16			type;		/* type of mapping */
	u16			flags;		/* flags for mapping */
	struct block_device	*bdev;		/* block device for I/O */
	struct dax_device	*dax_dev; 	/* dax_dev for dax operations */
	void			*inline_data;
	void			*private;	/* filesystem private */
	u64			validity_cookie; /* used with .iomap_valid() */
};

offset부터 length바이트 구간이 addr 위치(bdev·dax_dev·inline_data 중 하나에 실린)에 있다는 것을 구조체 하나로 표현한다. type 필드는 IOMAP_MAPPED(정상 매핑), IOMAP_INLINE(inode에 직접 저장된 작은 파일), IOMAP_HOLE(할당 안 됨, 읽으면 0 반환), IOMAP_DELALLOC(나중에 생성될 매핑), IOMAP_UNWRITTEN(공간은 있지만 아직 안 써져서 읽으면 0 반환) 중 하나를 나타낸다.

파일시스템은 iomap 계층이 호출하는 iomap_begin()/iomap_end() 콜백을 구현해 이 구조체를 채운다. iomap_begin()은 연산이 시작되기 전에 호출돼 해당 구간의 매핑을 준비하고, iomap_end()은 연산이 끝난 뒤 실제로 쓰인 바이트 수를 받아 정리 작업을 한다. 대부분의 파일시스템 기능(버퍼 읽기/쓰기, direct I/O, DAX I/O, 파일 내 seek, 페이지 폴트 처리, 파일 truncate 등)이 이 매핑 위에서 동작하는 상위 함수(iomap_read_folio(), iomap_writepages() 등)로 구현된다. 다만 이 상위 함수들의 문서화가 부실해서 파일시스템 개발자가 소스를 직접 뒤져야 하는 경우가 많은데, 6.11부터 Darrick Wong이 일부 문서를 추가했다.

iomap은 여전히 활발히 개발 중인 서브시스템이다. fs-verity 무결성 보호, T10 protection information 생성/검증, readahead 개선이 최근 추가됐고, iomap_begin()/iomap_end() 콜백을 iterator 기반 API로 교체하고 direct I/O 성능을 개선하는 작업이 진행 중이며, exfat·minix 파일시스템의 iomap 전환도 검토되고 있다.

LSFMM+BPF 서밋: negative dentry 제한 논의

2026 Linux Storage, Filesystem, Memory-Management, and BPF(LSFMM+BPF) 서밋에서는 negative dentry(디렉터리에 특정 이름의 파일이 없음을 캐싱하는 dentry) 과다 누적 문제가 다뤄졌다. Miklos Szeredi가 이끈 세션에서는, Ian Kent가 보고한 디렉터리당 수억 개의 negative dentry 사례가 소개됐다. 이 경우 fsnotify_set_children_dentry_flags() 호출이 디렉터리의 모든 dentry를 순회하다 soft lockup을 유발했다. struct dentry의 참조 카운트 락(d_lockref)이 오버플로우할 이론적 가능성도 있지만, 이는 20억 개의 dentry가 필요해 현실성은 낮다.

Amir Goldstein은 negative dentry를 d_children 리스트 끝으로 옮겨서 순회가 첫 negative dentry에서 멈출 수 있게 하자고 제안했다. 하지만 Chuck Lever는 getdents()로 노출되는 자식 dentry 순서가 바뀌어 호환성 문제가 생길 수 있다고 우려했고, Jan Kara는 negative dentry가 나중에 positive로 바뀔 때(파일 생성) 순서 문제가 생길 수 있다고 지적했다. David Howells는 아예 자료구조 자체를 교체하자고 제안했지만 구체안은 없었다.

Christian Brauner는 10년 넘게 이어진 문제라며, negative dentry 개수에 대한 heuristic 제한이 필요하다고 봤다. 기존 dentry-negative sysfs 노드를 확장하는 방안이 거론됐는데, 그는 “정책은 결국 사용자 공간이 담당하는 게 맞다”는 입장을 밝히며 OOM killer를 예로 들었다. Ted Ts’o는 “정상적인 워크로드라면” 디렉터리당 1,000개 제한이면 충분하지 않겠냐면서도, 실제로 그 이상이 필요한 워크로드 사례를 더 알고 싶다고 했다.

LSFMM+BPF 서밋: 더 빠른 RCU와 락 없는 메모리 할당

Puranjay Mohan은 RCU(read-copy-update) grace period 성능 개선 작업을 발표했다. synchronize_rcu()(일반, 수십 밀리초 소요)와 synchronize_rcu_expedited()(IPI로 강제 단축)는 서로 독립적으로 동작해서, expedited grace period가 끝나도 일반 grace period를 기다리던 콜백은 풀리지 않는 비효율이 있었다. Mohan은 콜백 리스트가 두 grace period 번호를 모두 추적하도록 rcu_exp_wait_wake(), rcu_pending(), rcu_core() 등 커널 내부 함수를 수정했다. 소켓 생성/파괴를 반복하는 스레드와 expedited grace period를 유발하는 스레드를 함께 돌린 벤치마크에서, 할당된 메모리가 33~41% 줄고 synchronize_rcu() 레이턴시도 감소했다. 다만 Alexei Starovoitov는 IPI 비용이 크기 때문에 메모리 회수만을 목적으로 expedited grace period를 요청하는 것은 권장하지 않는다고 선을 그었다.

이어진 세션에서 Harry Yoo와 Starovoitov는 kmalloc_nolock()을 소개했다. 지금까지 BPF map은 락 없이 접근하기 위해 메모리를 사전 할당해야 했는데, 이는 map을 다 채우지 않으면 메모리를 낭비하는 구조다. 이를 보완하려 만든 BPF 전용 할당자는 유지보수 부담이 크고 BPF 서브시스템 밖에서는 쓸 수 없었다. kmalloc_nolock()의 목표는 사전 할당을 되살리지 않으면서 이 전용 할당자를 걷어내는 것이다. 이를 위해 sleepable·non-sleepable 컨텍스트 양쪽에서 할당이 가능해야 하고, RCU critical section 안에서도 접근할 수 있어야 하며, “typesafety-by-RCU” 기법(같은 타입이라는 보장이 있을 때 해제 대기 중인 객체를 즉시 재활용하는 방식)으로 회수 지연을 줄일 수 있어야 한다.

실제로 BPF hashmap 구현에서는 원소를 해시 버킷에서 제거한 뒤, 키를 먼저 갱신하고 그다음 데이터를 갱신하는 순서를 지켜 리더가 잘못된 데이터를 읽지 않도록 한다. 이 방식으로 전체 RCU 사이클을 기다리지 않고도 메모리를 즉시 재사용할 수 있다. 세션에서는 kfree_nolock()kfree_rcu_nolock()의 필요성, 락 없이 할당 가능한 메모리가 없을 때 buddy allocator로 폴백하는 방안까지 논의됐다. Starovoitov는 “이번 논의로 명확해졌다”며 만족을 표했다.

LLM 지원 커널 패치 두 건, 엇갈린 반응

최근 커널 커뮤니티에는 LLM의 도움을 받아 작성된 패치가 급증하고 있는데, 대개 커뮤니티에 낯선 개발자들이 제출한다. 이번 주 메모리 관리(MM) 분야에서는 이례적으로 신뢰받는 베테랑 개발자 두 명이 각각 Claude Opus의 지원을 받아 작성한 대규모 패치 시리즈를 제출했고, 정반대의 반응을 얻었다.

1998년부터 메모리 단편화 논의에 참여해온 Rik van Riel은 hugetlbfs 예약 없이 1GB(PUD 레벨) huge page를 안정적으로 할당하는 40-part 패치 시리즈를 제출했다. 핵심 아이디어는 movable/unmovable 할당을 4MB 단위 page block보다 훨씬 큰 “super page block”(1GB) 단위로 분리 관리해, 하나의 unmovable 할당 때문에 1GB 전체가 영구적으로 단편화되는 것을 막는 것이다. 하지만 Lorenzo Stoakes는 “이 시리즈는 지금 상태로는 완전히 머지 불가능하다”며 강하게 비판했고, 일부 코드는 “__rmqueue_smallest()에 대한 코드 전쟁범죄”라고 표현했다. 그는 “LLM이 폭주하도록 놔둔 것 같다”고 지적하면서도 van Riel의 역량 자체는 인정했다. van Riel은 애초에 머지가 아니라 설계 단계 피드백을 받으려던 것이었다고 해명했지만, 결국 사람이 더 개입해 다시 작업해야 하는 상황이 됐다.

반면 Kiryl Shutsemau가 제출한, 가상머신(VM) 게스트 메모리의 working set을 호스트에 노출하기 위한 userfaultfd() 확장 패치 시리즈는 7차례 리비전을 거치는 동안 어느 리뷰에서도 LLM 사용 자체가 문제로 지적되지 않았다. Andrew Morton이 LLM을 어떻게 활용했는지 묻자 Shutsemau는 상세히 답했다. 먼저 아이디어를 다듬는 단계(“러버덕 디버깅의 스테로이드 버전”)로 LLM과 대화하고, 이후 계획을 세운 뒤 실행을 맡겼으며, 가장 시간이 많이 든 부분은 8~10라운드에 걸친 결과 코드 리뷰였고, 마지막에는 다른 프롬프트 세트로 전체 시리즈를 LLM에게 다시 검토시켰다고 밝혔다. 두 사례를 가른 것은 결국 사람이 코드 품질 검증에 얼마나 시간을 투자했는가였다는 것이 기사의 결론이다.

짧은 소식

  • Guix 취약점 4건: guix substitute에서 원격 권한 상승으로 이어질 수 있는 취약점 3건과, guix pull/guix time-machine에서 임의 경로에 파일을 생성·덮어쓸 수 있는 취약점 1건이 공개됐다. GNU Guix 프로젝트는 guixguix-daemon의 즉시 업그레이드를 권고했다.
  • OpenSSH 10.4 릴리스: ML-DSA-44와 Ed25519를 결합한 post-quantum 복합 서명 방식을 실험적으로 지원한다. 샌드박스 지원으로 컴파일된 경우, SECCOMP나 NO_NEW_PRIVS가 없는 리눅스 시스템에서는 이제 에러만 남기고 넘어가지 않고 아예 실행이 실패한다.
  • 커널 7.2-rc2 (7월 6일): 13,798개 커밋, 2,176명의 개발자(그중 418명이 첫 기여)가 참여했다. Linus Torvalds는 “7.1의 같은 시점보다 약간 작은 정상 범위”라고 평했다. 같은 주 7.1.3, 6.18.38, 6.12.95, 6.6.144, 6.1.177, 5.15.211, 5.10.260 stable 업데이트도 나왔다.
  • kernel.org /pub 트리 복구: 미러링 인프라 변경 작업 중 실수로 /pub 트리 전체가 비워지는 사고가 있었다. 원본 데이터 손실은 아니고 퍼블릭 미러 사본이 사라진 것으로, 삭제는 빨랐지만 복구는 느리다며 복구 작업이 진행 중이다.
  • 이주의 인용구(Christian Brauner): “다른 서브시스템처럼 우리도 AI가 생성한 패치·버그 리포트를 많이 받는데, 제출자가 마치 사우론의 입(Mouth of Sauron)처럼 행동하는 경우가 있다. 이건 받아들일 수 없고, 그런 패치는 무시되거나 우선순위가 크게 낮아질 것이다. 충분히 생각하지 않았거나 자기가 뭘 제출하는지 이해 못 하는 게 뻔히 보이는 장문의 vibe-coded RFC는 리뷰할 시간을 뺏을 뿐이다. 코드를 산더미로 던지거나 자잘한 패치를 끝없이 던져 이름을 커널에 올리는 건 성공 스토리가 아니다.”

이번 주 핵심 요약

  • 커널 crypto/CRC 라이브러리화는 단순히 API를 다듬는 수준이 아니라 성능(최대 2.5배, CRC는 케이스에 따라 훨씬 더)과 정확성(FIPS 자체 테스트, KUnit 커버리지)을 동시에 끌어올리는 작업으로 자리잡았다.
  • iomap은 buffer head의 한계를 극복하기 위해 만들어진 계층으로, 아직도 iterator 기반 API 전환과 direct I/O 성능 개선이 진행 중인 “바쁜 핵심 서브시스템”이다.
  • negative dentry 문제는 10년 넘게 방치돼 왔고, 커널 자료구조 변경보다 사용자 공간에 정책을 맡기는 방향(heuristic 제한)으로 무게가 실리고 있다.
  • RCU expedited grace period 활용과 kmalloc_nolock()은 각각 메모리 회수 지연과 BPF 전용 할당자 부담을 줄이려는 시도로, 실제 벤치마크에서 30%대 메모리 절감을 보였다.
  • 같은 Claude Opus 지원을 받았어도 결과는 극과 극이었다. 사람이 설계 검증과 코드 리뷰에 충분한 시간을 투자했는지가 커뮤니티 수용 여부를 갈랐고, Brauner의 인용구는 이 대비를 더 선명하게 보여준다.

원문: LWN.net Weekly Edition for July 9, 2026

답글 남기기