1P by neo 2달전 | favorite | 댓글 1개

64비트 time_t로의 전환 위험성

  • 32비트 time_t 타입 사용으로 인해 2038년에 32비트 애플리케이션이 오류를 일으킬 가능성이 있음
  • time_t를 64비트 타입으로 변경하는 것이 해결책으로 제시됨
  • Musl은 이미 전환 완료, glibc는 옵션으로 지원, Debian 등 여러 배포판은 전환 완료
  • Gentoo와 같은 소스 기반 배포판은 전환이 어려움

Large File Support로 돌아가기

  • 32비트 아키텍처는 파일 오프셋을 지정하는 off_t와 inode 번호를 지정하는 ino_t를 32비트로 사용
  • 이로 인해 2 GiB 이상의 파일을 열 수 없고, inode 번호가 32비트 범위를 초과하는 파일을 열 수 없음
  • Large File Support 도입으로 이 문제를 해결, glibc에서는 여전히 선택 사항
  • time64 지원을 위해 LFS 사용이 필요

어떤 ABI를 사용하는가?

  • 세 가지 가능한 서브-ABI:
    1. 32비트 타입을 사용하는 원래의 ABI
    2. 64비트 off_tino_t, 32비트 time_t를 사용하는 LFS
    3. LFS + 64비트 time_t를 사용하는 time64
  • glibc 빌드는 세 가지 변형과 호환 가능하지만, API에서 이러한 타입을 사용하는 라이브러리는 호환되지 않음

왜 ABI 변경이 나쁜가?

  • 32비트 타입을 64비트 타입으로 교체하는 것은 호환성을 깨뜨림
  • 구조체의 경우, time_t가 포함된 구조체는 필드 위치가 변경되어 잘못된 필드를 읽거나 쓸 수 있음
  • 함수 매개변수의 경우, 스택에 전달되는 매개변수의 위치가 변경되어 잘못된 매개변수를 읽거나 쓸 수 있음
  • 이러한 문제는 런타임 오류와 보안 문제를 야기할 수 있음

어떻게 안전하게 만들 수 있는가?

  • 세 가지 아이디어:
    1. 새로운 ABI를 구분하기 위해 플랫폼 튜플(CHOST) 변경
    2. 새로운 ABI를 위해 libdir 변경
    3. 서로 다른 서브-ABI를 사용하는 바이너리가 링크되지 않도록 바이너리 수준의 ABI 구분 도입

플랫폼 튜플 변경

  • 플랫폼 튜플은 툴체인이 타겟팅하는 플랫폼을 식별
  • 새로운 ABI를 도입하기 위해 벤더 필드를 변경하거나 libc 필드에 추가 ABI 명세를 추가
  • 예: i686-gentoo_t64-linux-gnu, i686-pc-linux-gnut64

libdir 변경

  • libdir은 라이브러리 설치 디렉토리의 기본 이름
  • time64 변형을 위해 libdir 값을 변경하여 새로운 libdir에 time64 라이브러리를 설치
  • 이로 인해 time64 실행 파일이 time32 라이브러리를 링크하지 않도록 방지
  • Portage의 preserved-libs 기능을 사용하여 기존 라이브러리를 보존

바이너리 호환성 보장

  • 서로 다른 ABI를 사용하는 바이너리를 혼합할 수 없음
  • ELF 클래스, 머신 식별자, 플래그 필드 등을 사용하여 호환성 확인
  • time32와 time64 시스템을 구분하기 위해 새로운 ELF 노트 섹션 추가 고려

오래된 사전 빌드 애플리케이션

  • 오래된 사전 빌드 애플리케이션은 시스템 라이브러리와의 호환성 문제와 y2k38 문제에 직면
  • 멀티리브 레이아웃을 사용하여 호환성 문제 해결 가능
  • y2k38 문제는 시스템 시간을 조작하거나 VM을 사용하는 방법으로 해결 가능

GN⁺의 정리

  • 2038년 이후 32비트 time_t를 사용하는 애플리케이션이 오류를 일으킬 가능성이 있음
  • 64비트 time_t로 전환이 필요하지만, 이는 ABI 변경을 수반하여 복잡한 문제를 야기함
  • 플랫폼 튜플 변경, libdir 변경, 바이너리 호환성 보장을 통해 안전한 전환 경로를 제공할 수 있음
  • 오래된 사전 빌드 애플리케이션은 별도의 호환성 문제와 y2k38 문제를 해결해야 함
Hacker News 의견
  • Gentoo는 패키지를 설치하지 않고 빌드하는 옵션이 부족함

    • Gentoo는 패키지 빌드와 설치가 한 단계로 이루어짐
    • ABI 변경 시 업데이트 중에 시스템이 쉽게 깨질 수 있음
    • 64비트 time_t 문제는 널리 알려진 ABI 변경의 예시임
  • .so 버전 관리를 통해 ABI 변경을 처리하는 방법

    • .so 파일은 버전 번호를 포함함
    • 패키지 자체가 내부적으로 버전 번호를 관리함
    • 64비트 time_t를 지원하려면 상속된 ABI를 제어할 수 있는 추가 구성 요소가 필요함
  • Mac OS X에서 off_tino_t를 처리한 방법

    • 기존 호출과 구조체는 그대로 유지됨
    • 새로운 호출과 타입에 64 접미사가 추가됨
    • 빌드 시 컴파일된 바이너리가 실행될 최소 OS 버전을 지정할 수 있음
  • Debian은 64비트 time_t로 전환하는 데 어려움을 겪었음

    • 소스 기반 배포판은 더 어려운 전환 과정을 겪음
  • 32비트 유닉스 시스템에서 time_t를 unsigned 32비트로 대체한 경험

    • 2038년 이후 68년을 더 사용할 수 있게 됨
    • 유닉스 에포크 이전의 날짜를 표현할 수 없음
  • FreeBSD에서 amd64 포트를 할 때 64비트 time_t를 도입한 경험

    • 32비트 함수 인자가 64비트로 자동 변환됨
    • 초기부터 64비트 time_t를 사용하여 문제를 피함
    • tzcode가 64비트 안전하지 않아서 일부 문제를 겪음
  • BSD 매뉴얼 페이지의 "Bugs" 섹션에 있는 농담

    • "You can tune a file system, but you can't tune a fish."
  • 소스 기반 배포판 대신 Debian 같은 비소스 기반 배포판으로 전환하고 싶다는 의견

  • 32비트 time_t와 64비트 time_t의 구조체 오프셋 차이

    • 64비트 타입에서는 b가 64비트 정렬이 필요하여 패딩이 추가됨
  • C에서 타입 별칭이 나중에 변경될 가능성을 제공한다고 생각했지만, 실제로는 그렇지 않음

  • 문제를 빨리 해결하는 것이 좋다는 의견

    • OpenBSD는 모든 아키텍처에서 64비트 time_t를 사용함