신기한 Lobsters · 2026-10-22

"C 언어 안 쓰고 errno 가져오기"… 해외 개발자의 기괴한 시스템 해킹 수준 꼼수

핵심 요약
  • C 언어로 작성된 래퍼 함수나 비표준 구현체 의존 없이 타 프로그래밍 언어에서 C의 errno 값을 이식성 있게 가져오는 엽기적인 기법이 공개되었습니다.
  • libc에 errno 값을 바로 주는 함수는 없지만 perror가 있다는 점을 이용해, 프로그램 시작 시 stderr 디스크립터를 임시 파일로 가로채 에러 문자열을 캡처했습니다.
  • 미리 만들어 둔 0~255번 에러 문자열 테이블과 캡처한 메시지를 비교해 최종 errno 정수 값을 역으로 알아내는 엽기적인 구조로 구현되었습니다.
요약 C 언어가 아닌 다른 프로그래밍 언어(작성자의 경우 헤어(Hare) 언어)에서 libc 함수를 직접 호출할 때, 표준 C의 매크로로 정의된 오류 코드 'errno'의 실제 값을 가져오는 작업은 까다롭기로 유명합니다. 매크로의 전개 방식이 플랫폼마다 다르고 안정적인 호환성을 보장하지 않기 때문에, 통상적으로는 C로 간단한 래퍼 함수를 작성해 이를 반환받거나 특정 구현체의 세부 사항에 의존해야 합니다. 하지만 작성자는 C 래퍼 함수를 전혀 쓰지 않고 온전히 외부 언어에서 이식성 있게 errno 값을 알아내기 위한 충격적인 기교를 고안했습니다. libc 내부에는 errno의 숫자 값을 직접 반환하는 범용 함수가 없지만, errno에 해당하는 에러 문자열을 표준 에러(stderr)로 출력해주는 'perror' 함수가 있다는 점에 착안한 것입니다. 문제는 실제 콘솔 창에 에러가 출력되어서는 안 된다는 점이었습니다. 이를 해결하기 위해 프로그램 초기화(@init) 단계에서 표준 에러 파일 디스크립터(STDERR_FILENO, 2번)를 복제(dup)해 두고, 임시 파일을 생성(mkstemp)한 뒤 dup2를 이용해 stderr가 이 임시 파일을 가리키도록 강제로 바꿔버렸습니다. 이후 에러가 발생해 errno를 확인해야 할 때 perror(null)을 호출하면 에러 문자열이 콘솔이 아닌 임시 파일에 기록되며, lseek과 read를 통해 해당 임시 파일에 적힌 에러 문자열을 메모리로 읽어옵니다. 여기서 끝이 아닙니다. 에러 메시지 문자열을 다시 원래의 정수형 'errno' 값으로 역추적하기 위해, 초기화 시점에 strerror(0)부터 strerror(255)까지 미리 순회하며 에러 번호별 문자열 테이블을 만들어 둡니다. 그 후 임시 파일에서 읽어온 perror의 출력 결과와 이 테이블의 문자열들을 strcmp로 대조하여 최종적으로 일치하는 인덱스를 찾아 errno 정수 값으로 반환하는 구조를 완성했습니다. 시스템 호출과 파일 디스크립터 조작, 역방향 테이블 탐색까지 동원된 이 기괴한 발상에 해외 개발자 커뮤니티는 경악 섞인 감탄을 보냈습니다.
Sponsored · 광고