1 điểm bởi GN⁺ 2024-09-30 | 1 bình luận | Chia sẻ qua WhatsApp

Rủi ro của việc chuyển sang time_t 64-bit

  • Việc sử dụng kiểu time_t 32-bit có thể khiến các ứng dụng 32-bit gặp lỗi vào năm 2038
  • Việc đổi time_t sang kiểu 64-bit được đưa ra như một giải pháp
  • Musl đã hoàn tất chuyển đổi, glibc hỗ trợ dưới dạng tùy chọn, và nhiều bản phân phối như Debian cũng đã hoàn tất chuyển đổi
  • Các bản phân phối dựa trên mã nguồn như Gentoo gặp nhiều khó khăn hơn trong việc chuyển đổi

Quay lại Large File Support

  • Kiến trúc 32-bit sử dụng off_t để chỉ định file offset và ino_t để chỉ định số inode dưới dạng 32-bit
  • Vì vậy không thể mở tệp lớn hơn 2 GiB, và cũng không thể mở các tệp có số inode vượt quá phạm vi 32-bit
  • Large File Support đã được đưa vào để giải quyết vấn đề này, nhưng trên glibc đây vẫn là tùy chọn
  • Cần sử dụng LFS để hỗ trợ time64

Dùng ABI nào?

  • Có ba sub-ABI khả dĩ:
    1. ABI gốc dùng các kiểu 32-bit
    2. LFS dùng off_tino_t 64-bit, cùng time_t 32-bit
    3. time64 dùng LFS + time_t 64-bit
  • Bản dựng glibc có thể tương thích với cả ba biến thể, nhưng các thư viện dùng các kiểu này trong API thì không tương thích

Vì sao thay đổi ABI lại là điều xấu?

  • Việc thay các kiểu 32-bit bằng kiểu 64-bit sẽ phá vỡ tính tương thích
  • Với struct, các struct có chứa time_t sẽ thay đổi vị trí trường, dẫn đến việc đọc hoặc ghi nhầm trường
  • Với tham số hàm, vị trí tham số được truyền trên stack sẽ thay đổi, dẫn đến việc đọc hoặc ghi nhầm tham số
  • Những vấn đề này có thể gây ra lỗi runtime và cả vấn đề bảo mật

Làm thế nào để an toàn hơn?

  • Có ba ý tưởng:
    1. Thay đổi platform tuple (CHOST) để phân biệt ABI mới
    2. Thay đổi libdir cho ABI mới
    3. Đưa vào cơ chế phân biệt ABI ở mức binary để ngăn các binary dùng sub-ABI khác nhau liên kết với nhau

Thay đổi platform tuple

  • Platform tuple dùng để nhận diện nền tảng mà toolchain nhắm tới
  • Để đưa vào ABI mới, có thể thay đổi trường vendor hoặc thêm đặc tả ABI mới vào trường libc
  • Ví dụ: i686-gentoo_t64-linux-gnu, i686-pc-linux-gnut64

Thay đổi libdir

  • libdir là tên mặc định của thư mục cài đặt thư viện
  • Có thể đổi giá trị libdir cho biến thể time64 để cài các thư viện time64 vào libdir mới
  • Điều này giúp ngăn file thực thi time64 liên kết với thư viện time32
  • Có thể dùng tính năng preserved-libs của Portage để giữ lại các thư viện hiện có

Đảm bảo tương thích nhị phân

  • Không thể trộn lẫn các binary dùng ABI khác nhau
  • Có thể dùng ELF class, machine identifier, trường cờ và các cơ chế khác để kiểm tra tính tương thích
  • Cũng đang cân nhắc thêm một ELF note section mới để phân biệt hệ thống time32 và time64

Các ứng dụng dựng sẵn cũ

  • Các ứng dụng dựng sẵn cũ gặp cả vấn đề tương thích với thư viện hệ thống lẫn vấn đề y2k38
  • Có thể giải quyết vấn đề tương thích bằng bố cục multilib
  • Vấn đề y2k38 có thể được xử lý bằng cách thao tác thời gian hệ thống hoặc dùng VM

Tóm tắt của GN⁺

  • Sau năm 2038, các ứng dụng dùng time_t 32-bit có thể gặp lỗi
  • Cần chuyển sang time_t 64-bit, nhưng việc này kéo theo thay đổi ABI và gây ra nhiều vấn đề phức tạp
  • Có thể cung cấp lộ trình chuyển đổi an toàn thông qua thay đổi platform tuple, thay đổi libdir và đảm bảo tương thích nhị phân
  • Các ứng dụng dựng sẵn cũ cần giải quyết riêng các vấn đề tương thích và vấn đề y2k38

1 bình luận

 
GN⁺ 2024-09-30
Ý kiến trên Hacker News
  • Gentoo thiếu tùy chọn chỉ build mà không cài đặt gói

    • Trên Gentoo, việc build và cài đặt gói diễn ra trong một bước
    • Khi ABI thay đổi, hệ thống có thể dễ dàng bị hỏng trong lúc cập nhật
    • Vấn đề time_t 64-bit là một ví dụ điển hình về thay đổi ABI đã được biết đến rộng rãi
  • Cách xử lý thay đổi ABI thông qua quản lý phiên bản .so

    • Tệp .so có kèm số phiên bản
    • Bản thân gói tự quản lý số phiên bản ở bên trong
    • Để hỗ trợ time_t 64-bit, cần thêm các thành phần cấu hình có thể kiểm soát ABI được kế thừa
  • Cách Mac OS X xử lý off_tino_t

    • Các lời gọi và cấu trúc hiện có được giữ nguyên
    • Các lời gọi và kiểu mới được thêm hậu tố 64
    • Khi build, có thể chỉ định phiên bản OS tối thiểu để binary đã biên dịch có thể chạy
  • Debian đã gặp khó khăn khi chuyển sang time_t 64-bit

    • Các bản phân phối dựa trên mã nguồn còn trải qua quá trình chuyển đổi khó khăn hơn
  • Kinh nghiệm thay time_t trên các hệ thống Unix 32-bit bằng unsigned 32-bit

    • Nhờ đó có thể dùng thêm 68 năm sau năm 2038
    • Không thể biểu diễn các ngày trước Unix epoch
  • Kinh nghiệm đưa time_t 64-bit vào khi port amd64 trên FreeBSD

    • Các đối số hàm 32-bit được tự động chuyển thành 64-bit
    • Dùng time_t 64-bit ngay từ đầu để tránh vấn đề
    • Đã gặp một số vấn đề vì tzcode không an toàn với 64-bit
  • Trò đùa trong mục "Bugs" của trang man BSD

    • "You can tune a file system, but you can't tune a fish."
  • Có ý kiến muốn chuyển từ bản phân phối dựa trên mã nguồn sang bản phân phối không dựa trên mã nguồn như Debian

  • Khác biệt về offset trong struct giữa time_t 32-bit và time_t 64-bit

    • Với kiểu 64-bit, b cần căn chỉnh 64-bit nên padding được thêm vào
  • Từng nghĩ rằng bí danh kiểu trong C cho phép thay đổi về sau, nhưng thực tế không phải vậy

  • Có ý kiến cho rằng nên giải quyết vấn đề này càng sớm càng tốt

    • OpenBSD dùng time_t 64-bit trên mọi kiến trúc