1 ポイント 投稿者 GN⁺ 2024-09-30 | 1件のコメント | WhatsAppで共有

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 は3種類ある:
    1. 32ビット型を使う元の ABI
    2. 64ビットの off_tino_t、32ビットの time_t を使う LFS
    3. LFS + 64ビット time_t を使う time64
  • glibc のビルドは3つの変種すべてと互換性を持てるが、API でこれらの型を使うライブラリは互換にならない

なぜ ABI 変更はよくないのか?

  • 32ビット型を64ビット型に置き換えると互換性が壊れる
  • 構造体では、time_t を含む構造体でフィールド位置が変わり、誤ったフィールドを読み書きする可能性がある
  • 関数パラメータでは、スタックに渡される引数の位置が変わり、誤った引数を読み書きする可能性がある
  • こうした問題はランタイムエラーやセキュリティ問題を引き起こしうる

どうすれば安全にできるか?

  • 3つのアイデア:
    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 問題に対処する必要がある

1件のコメント

 
GN⁺ 2024-09-30
Hacker News の意見
  • Gentoo には、パッケージをインストールせずにビルドする選択肢が不足している

    • Gentoo ではパッケージのビルドとインストールが1段階で行われる
    • 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ビット Unix システムで time_t を unsigned 32ビットに置き換えた経験

    • 2038年以降もさらに68年間使用できるようになった
    • Unix エポック以前の日付は表現できない
  • 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 を使用している