ความเสี่ยงของการเปลี่ยนไปใช้ time_t แบบ 64 บิต
- การใช้ชนิด
time_t แบบ 32 บิตอาจทำให้แอปพลิเคชัน 32 บิตเกิดข้อผิดพลาดในปี 2038
- มีการเสนอให้เปลี่ยน
time_t เป็นชนิด 64 บิตเพื่อแก้ปัญหา
- Musl เปลี่ยนผ่านเสร็จแล้ว, glibc รองรับแบบเป็นตัวเลือก, และดิสทริบิวชันหลายราย เช่น Debian ก็เปลี่ยนผ่านเสร็จแล้ว
- ดิสทริบิวชันแบบ source-based เช่น Gentoo เปลี่ยนผ่านได้ยาก
ย้อนกลับไปที่ Large File Support
- สถาปัตยกรรม 32 บิตใช้
off_t สำหรับระบุ file offset และ ino_t สำหรับระบุหมายเลข inode ในรูปแบบ 32 บิต
- ส่งผลให้ไม่สามารถเปิดไฟล์ที่มีขนาดเกิน 2 GiB ได้ และไม่สามารถเปิดไฟล์ที่มีหมายเลข inode เกินช่วง 32 บิตได้
- การนำ Large File Support มาใช้ช่วยแก้ปัญหานี้ โดยใน glibc ยังคงเป็นตัวเลือก
- การรองรับ time64 จำเป็นต้องใช้ LFS
ใช้ ABI แบบใด?
- มี sub-ABI ที่เป็นไปได้ 3 แบบ:
- ABI ดั้งเดิมที่ใช้ชนิด 32 บิต
- LFS ที่ใช้
off_t และ ino_t แบบ 64 บิต แต่ใช้ time_t แบบ 32 บิต
- time64 ที่ใช้ LFS +
time_t แบบ 64 บิต
- การบิลด์ glibc สามารถเข้ากันได้กับทั้ง 3 แบบ แต่ไลบรารีที่ใช้ชนิดเหล่านี้ใน API จะไม่เข้ากัน
ทำไมการเปลี่ยน ABI ถึงเป็นเรื่องไม่ดี?
- การแทนที่ชนิด 32 บิตด้วยชนิด 64 บิตทำให้ความเข้ากันได้พัง
- ในกรณีของ struct หากมี
time_t อยู่ภายใน struct ตำแหน่งของฟิลด์จะเปลี่ยนไป ทำให้อ่านหรือเขียนฟิลด์ผิดได้
- ในกรณีของพารามิเตอร์ฟังก์ชัน ตำแหน่งของพารามิเตอร์ที่ส่งผ่านบนสแตกจะเปลี่ยนไป ทำให้อ่านหรือเขียนพารามิเตอร์ผิดได้
- ปัญหาเหล่านี้อาจนำไปสู่ข้อผิดพลาดขณะรันไทม์และปัญหาด้านความปลอดภัย
จะทำให้ปลอดภัยได้อย่างไร?
- มี 3 แนวคิด:
- เปลี่ยน platform tuple (
CHOST) เพื่อแยก ABI ใหม่
- เปลี่ยน libdir สำหรับ ABI ใหม่
- เพิ่มการแยก ABI ในระดับไบนารี เพื่อป้องกันไม่ให้ไบนารีที่ใช้ sub-ABI ต่างกันถูกลิงก์เข้าด้วยกัน
การเปลี่ยน platform tuple
- platform tuple ใช้ระบุแพลตฟอร์มที่ toolchain ตั้งเป้าไว้
- หากต้องการนำ ABI ใหม่มาใช้ สามารถเปลี่ยนฟิลด์ vendor หรือเพิ่มข้อกำหนด ABI เพิ่มเติมในฟิลด์ libc
- ตัวอย่าง:
i686-gentoo_t64-linux-gnu, i686-pc-linux-gnut64
การเปลี่ยน libdir
- libdir คือชื่อพื้นฐานของไดเรกทอรีติดตั้งไลบรารี
- สำหรับ time64 สามารถเปลี่ยนค่า libdir เพื่อติดตั้งไลบรารี time64 ลงใน libdir ใหม่
- วิธีนี้ช่วยป้องกันไม่ให้ไฟล์ปฏิบัติการ time64 ไปเชื่อมลิงก์กับไลบรารี time32
- ใช้ฟีเจอร์
preserved-libs ของ Portage เพื่อเก็บรักษาไลบรารีเดิมไว้
การรับประกันความเข้ากันได้ของไบนารี
- ไม่สามารถผสมไบนารีที่ใช้ ABI ต่างกันได้
- ใช้ ELF class, machine identifier, flag field ฯลฯ เพื่อตรวจสอบความเข้ากันได้
- มีการพิจารณาเพิ่ม ELF note section ใหม่เพื่อแยกระบบ time32 และ time64
แอปพลิเคชันแบบ prebuilt รุ่นเก่า
- แอปพลิเคชันแบบ prebuilt รุ่นเก่าจะเจอทั้งปัญหาความเข้ากันได้กับไลบรารีของระบบและปัญหา y2k38
- สามารถแก้ปัญหาความเข้ากันได้ด้วยการใช้เลย์เอาต์แบบ multilib
- สำหรับปัญหา y2k38 อาจแก้ได้ด้วยการปรับเวลาในระบบหรือใช้ VM
สรุปโดย GN⁺
- หลังปี 2038 แอปพลิเคชันที่ใช้
time_t แบบ 32 บิตอาจเกิดข้อผิดพลาดได้
- จำเป็นต้องเปลี่ยนไปใช้
time_t แบบ 64 บิต แต่การทำเช่นนั้นมาพร้อมกับการเปลี่ยน ABI และก่อให้เกิดปัญหาที่ซับซ้อน
- สามารถจัดทำเส้นทางการเปลี่ยนผ่านอย่างปลอดภัยได้ด้วยการเปลี่ยน platform tuple, เปลี่ยน libdir และรับประกันความเข้ากันได้ของไบนารี
- แอปพลิเคชันแบบ prebuilt รุ่นเก่ายังต้องแก้ปัญหาความเข้ากันได้เฉพาะทางและปัญหา y2k38 แยกต่างหาก
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
Gentoo มีตัวเลือกสำหรับคอมไพล์โดยไม่ติดตั้งแพ็กเกจค่อนข้างน้อย
time_tแบบ 64 บิตเป็นตัวอย่างของการเปลี่ยน ABI ที่เป็นที่รู้จักกันอย่างกว้างขวางวิธีจัดการการเปลี่ยน ABI ผ่านการจัดการเวอร์ชันของ
.so.soมีหมายเลขเวอร์ชันรวมอยู่ด้วยtime_tแบบ 64 บิต จำเป็นต้องมีองค์ประกอบเพิ่มเติมที่สามารถควบคุม ABI ที่สืบทอดมาได้วิธีที่ Mac OS X จัดการกับ
off_tและino_t64ให้กับการเรียกและชนิดข้อมูลใหม่Debian เคยประสบปัญหาในการเปลี่ยนไปใช้
time_tแบบ 64 บิตประสบการณ์การแทนที่
time_tบนระบบยูนิกซ์ 32 บิตด้วย unsigned 32 บิตประสบการณ์การนำ
time_tแบบ 64 บิตมาใช้ตอนทำพอร์ต amd64 ของ FreeBSDtime_tแบบ 64 บิตตั้งแต่แรกจึงหลีกเลี่ยงปัญหาได้tzcodeยังไม่ปลอดภัยกับ 64 บิตมุกตลกในส่วน "Bugs" ของหน้าแมนนวล BSD
มีความเห็นว่าอยากย้ายจากดิสโทรแบบ source-based ไปใช้ดิสโทรที่ไม่ใช่ source-based อย่าง Debian
ความต่างของออฟเซ็ตในโครงสร้างระหว่าง
time_tแบบ 32 บิตและ 64 บิตbต้องการการจัดแนว 64 บิต จึงมีการเพิ่ม paddingเคยคิดว่าการใช้ type alias ใน C เปิดโอกาสให้เปลี่ยนได้ภายหลัง แต่ในความเป็นจริงไม่ได้เป็นเช่นนั้น
มีความเห็นว่าควรรีบแก้ปัญหานี้ให้เร็ว
time_tแบบ 64 บิตบนทุกสถาปัตยกรรม