IT 및 AI

Linux 7.2, 6년간 360개 이상 패치 끝에 strncpy API 제거 — 버그의 온상이 사라졌다

푸른강아지 2026. 6. 23. 14:56
반응형

Linux 7.2, 6년간 360개 이상 패치 끝에 strncpy API 제거 — 버그의 온상이 사라졌다

리눅스 커널 개발자들에게 오랫동안 숙제로 남아 있던 과제가 드디어 마무리됐다. Linux 7.2 개발 브랜치 머지 윈도우에서 C 표준 문자열 복사 함수 strncpy()가 커널 소스 트리 전체에서 완전히 제거됐다. 무려 6년, 362개 커밋이 투입된 대장정이었다.

 

strncpy는 왜 위험했나

strncpy()는 초기 Unix 시절 고정 너비 문자열 필드를 처리하기 위해 설계된 함수로, 현대 커널 환경과는 맞지 않는 두 가지 근본적인 문제를 안고 있었다.

  • 오버플로우 시 NUL 종단 미보장 — 소스 문자열이 목적지 버퍼보다 길거나 같으면 NUL 문자(\0)를 붙이지 않는다. 이후 C 문자열로 읽으면 버퍼 끝을 넘어 메모리에 있는 임의의 바이트까지 읽어버리는 버퍼 오버리드(buffer over-read)가 발생한다. 이는 커널 메모리 정보 유출(memory disclosure) 취약점으로 이어질 수 있다.
  • 언더플로우 시 강제 제로필(zero-fill) — 목적지 버퍼가 256바이트인데 10바이트 문자열만 복사했다면, 나머지 246바이트를 모두 0으로 채우는 불필요한 쓰기 연산이 발생한다. 성능 저하의 요인이다.

커널 문서는 strncpy()"적극적으로 위험한(actively dangerous)" 함수라고 명시하고 있었다. 이미 2024년 1월에는 선배 격인 strlcpy()가 먼저 제거된 바 있다.

 

362개 커밋의 의미 — 단순 치환이 아닌 감사(Audit)의 과정

단순히 strncpystrscpy로 일괄 치환하는 작업이 아니었다. strncpy의 각 호출 지점은 실제로 의도한 동작이 무엇인지가 모두 달랐기 때문이다.

TechTimes의 분석에 따르면, 커널은 strncpy다섯 가지 서로 다른 의미의 메모리 연산에 사용하고 있었다. 각각의 호출 지점을 분석해 적절한 대체 함수로 교체하는 작업은 곧 커널 전체에 대한 코드베이스 감사(codebase-wide audit)였다.

이 프로젝트를 주도한 것은 Google의 Kees Cook(커널 자기 보호 프로젝트, Kernel Self Protection Project). Cook은 이 작업을 "커널 커뮤니티가 퀵픽스를 거부하고 장기적인 위생을 추구하는 전형적인 사례"라고 표현했다.

 

다섯 가지 대체 함수

strncpy가 감추고 있던 다섯 가지 의미를 각각 명시적인 함수로 분리한 것이 핵심이다:

/* 1. NUL-terminated 문자열 — 표준 대체 */ strscpy(dst, src, size); // 항상 NUL 종단, 음수 반환 시 절단 /* 2. NUL-terminated + 제로 패딩 필요 시 */ strscpy_pad(dst, src, size); /* 3. 고정 너비 필드 (WiFi ESSID 등, NUL 종단 불필요) */ strtomem_pad(dst, src, size); /* 4. 명시적 패딩이 있는 바운디드 복사 */ memcpy_and_pad(dst, dst_size, src, src_size, pad_char); /* 5. 이미 길이를 아는 메모리 복사 */ memcpy(dst, src, len); // 문자열 의미 없음

특히 strscpy()는 이전에 사용되던 strlcpy()보다 더 안전하다. strlcpy는 절단(truncation)이 발생해도 소스 전체를 끝까지 읽는 반면(소스 측 오버리드 위험), strscpy는 복사한 만큼만 읽는다.

 

컴파일 타임 강제 — 리뷰에 의존하던 시대의 종말

이번 변경의 가장 큰 의미는 정책이 아키텍처 제약으로 전환된 점이다. 더 이상 코드 리뷰에서 "strncpy 쓰지 마세요"라고 말할 필요가 없다. strncpy가 소스 트리에 존재하지 않으므로, 컴파일러가 먼저 잡아낸다.

이는 신규 커널 기여자에게도 중요하다. 복잡한 코드 리뷰 지침을 숙지하지 않아도, 잘못된 함수를 사용하는 패치 자체가 컴파일되지 않으므로 실수를 원천 차단할 수 있다.

 

일정 및 영향 범위

  • 머지 완료: 2026년 6월 20일 (Linux 7.2 개발 트리)
  • Linux 7.2 정식 릴리스: 2026년 8월 30일 예상
  • 우분투 26.10: Linux 7.2 탑재, 2026년 10월 출시 예정

📌 사용자 공간(C 표준 라이브러리)에는 영향 없음
strncpy()는 glibc 등 C 표준 라이브러리에 계속 존재한다. 이 변경은 커널 소스 트리 내부에서만 적용되므로, 일반 애플리케이션 개발자는 영향을 받지 않는다. 커널 모듈 작성자만 주의하면 된다.

 

개발자들이 할 말

Slashdot 댓글에서는 다양한 반응이 나왔다. 한 댓글 작성자는 strncpy"애초부터 잘못 설계됐다. 복사하고 NUL 종단하는데, 종단하지 않을 때가 있다"며 근본적인 설계 결함을 지적했다. 다른 이는 "절단(truncation) 시 항상 NUL 종단하지 않는 이유를 모르겠다"며 공감했다.

유머 섞인 반응도 눈에 띄었다. 한 댓글은 "strncpy를 없앴다고? 좋아, strcpy를 쓰면 되겠네"라고 빈정댔고, 또 다른 이는 "Rust를 쓰니까 내 소스도 컴파일할 메모리가 부족하다"며 익명으로 농담을 던졌다.

 

의미와 교훈

이번 사건이 주는 교훈은 단순하다. 위험한 API를 없애는 가장 확실한 방법은 물리적으로 존재하지 않게 만드는 것이다. 문서화, 교육, 코드 리뷰만으로는 한계가 있다. 컴파일러 수준에서 차단해야 실수가 근절된다.

362개의 패치, 6년의 시간. 하나의 레거시 함수를 완전히 제거하는 데 이토록 긴 시간이 걸린 것은, 각각의 호출 지점이 저마다 다른 의도로 사용되고 있었기 때문이다. 그럼에도 리눅스 커널 커뮤니티는 포기하지 않았다. 그 결과, 이제 모든 문자열 복사 연산의 의도가 함수 이름 자체에 명시적으로 드러나게 되었다.

이는 소프트웨어 엔지니어링의 오랜 교훈을 다시 한번 상기시킨다: "좋은 인터페이스는 오용하기 어렵다."

 
 
반응형