6 ポイント 投稿者 GN⁺ 2026-03-30 | 2件のコメント | WhatsAppで共有
  • initrdをカーネルが直接解釈して実行するプログラム単位として定義し、Linuxを一種のインタプリタとして再解釈する
  • kexecbase64cpioを使って自分自身を再起動する再帰型Linuxディストリビューションを構成し、initrdが自らを再実行する
  • /initスクリプトが自身のcpioイメージを出力するようにすると、Quine形式の自己複製initrdが成立する
  • ELF実行構造とld.sobinfmt_miscを通じて、インタプリタ階層がカーネルまで続く構造を説明する
  • kexecやQEMUを活用すると、Linux上で別のLinuxを末尾再帰的に実行でき、カーネル・仮想化・インタプリタの境界を実験的に拡張する

rkx.gzのリバースエンジニアリングと自己再帰型initrd構造

  • curl https://astrid.tech/rkx.gz | gunzip | sudo sh コマンドは、20MBサイズのbase64エンコードされたシェルスクリプトをダウンロードして実行する
    • スクリプトはroot権限を確認し、kexecbase64cpioの存在を検査する
    • base64データをデコードしてrというcpioアーカイブを作成し、その中からkというカーネルイメージを抽出する
    • kexecを使ってkをカーネルに、rをラムディスクとしてロードして実行する
  • r.cpioの内部には/bin/initkファイルが含まれ、kLinux 6.18.18カーネルイメージ/initはシェルスクリプト形式である
    • /init/procをマウントし、/rに現在のファイルシステムをcpioで束ねた後、kexec/k/rを再実行する
    • 結果として自分自身を継続的に再起動する再帰型Linuxディストリビューションになる

Linuxカーネルをインタプリタとみなす視点

  • initrdは単なるブート用ラムディスクではなく、Linuxカーネルが解釈して実行するプログラムとみなせる
    • curl | shpython3 script.pyのように、initrdもカーネルによって実行される入力プログラムの形である
    • したがってLinuxカーネルはinitrdを解釈するインタプリタとして機能する
  • この構造は**末尾再帰最適化(tail-call optimization)**に似ている
    • kexecは以前のカーネルを上書きせず、新しいメモリ空間にロードして実行する
    • 各カーネルは以前の状態を保持せず、新しい「スタックフレーム」に置き換えられる

Quineとinitrdの自己複製

  • Quineは自分自身を出力するプログラムを意味する
    • /initスクリプトが最後にcat /rを実行するようにすると、自身と同一のcpioを出力する
    • この場合、Linux initrdインタプリタのQuineが成立する
    • すべてのファイルはRAM上のtmpfsに存在するため、実際のディスクI/Oは発生しない

ELF、ld.so、そしてインタプリタの階層

  • ELF実行ファイルはヘッダに**インタプリタ(ld-linux-x86-64.so.2)**のパスを含む
    • 実行時、カーネルはld.soを先に実行し、ld.soがELFの動的ライブラリを読み込んだ後にプログラムを実行する
    • したがってELFも一種のインタプリタ言語とみなせる
  • /bin/shld.soによって解釈され、ld.soはカーネルが直接解釈する
    • ld.soは静的リンクされたELFなので、カーネルが直接実行できる
    • これによって**インタプリタ階層の基底ケース(base case)**が成立する

binfmt_miscによるCPIO実行

  • binfmt_miscを使うと、特定のマジックバイトを持つファイルを指定したインタプリタで実行できる
    • 例の登録コマンド:
      echo ':cpio:M::\x30\x37\x30\x37\x30\x31::/path/to/my/script.sh:' > /proc/sys/fs/binfmt_misc/register
      
    • この設定により、chmod +xされたCPIOファイルを直接実行できる
  • QEMUを使ってCPIOをinitrdとして実行するスクリプトをインタプリタとして登録できる
    • QEMUは指定されたカーネルとinitrdを使って仮想マシンを起動する
    • 結果としてCPIOファイルのインタプリタはQEMUが起動するLinuxカーネルになる

再帰的インタプリタと「最も奇妙なループ」

  • QEMUベースのインタプリタは、新しいLinux環境のスタックフレームを生成する
    • Linux上で別のLinuxを実行する構造であり、メモリの限界まで入れ子にできる
    • kexecベースのインタプリタに置き換えると、末尾呼び出し最適化された再帰型Linux実行が可能になる
  • /initでbinfmt_miscを登録し、/rを実行するように構成すると 自分自身を実行するinitrdが完成する
    • /rはCPIOフォーマットの次のinitプロセスであり、実行時に再び自分自身を解釈する

結論

  • initrdは単なるブートツールではなく、Linuxカーネルが解釈するプログラム単位である
  • kexecbinfmt_miscを使えば、Linux自体をインタプリタのように再帰的に実行できる
  • この構造はカーネル、仮想化、インタプリタ、自己複製プログラムの境界を取り払う実験的な概念である
  • 関連ソースコードはGitHubリポジトリ ifd3f/rekexec で公開されている

2件のコメント

 
github88 2026-03-31

無知だと大胆になるというけれど……こういう文章は控えてほしいです。

 
GN⁺ 2026-03-30
Hacker Newsの意見
  • この記事を読みながら、あまりに多くの誤解のせいでつらかった
    cpioアーカイブはファイルシステムではない。筆者はinitramfsを使っているが、これはtmpfsベースだ。Linuxはcpioをtmpfsに展開できる。ファイルとディレクトリのアーカイブは、それ自体がプログラムではない
    何かが似て見えるからといって同じとは限らない。バイナリプログラムはCPU上で実行され、もしインタプリタがあるなら、それはハードウェア環境の中に隠れている。これはカーネルの範囲外だ
    シェルスクリプトを実行するには、そのスクリプトを解釈するシェルが必要だ。筆者はこの部分を省略して、カーネルとシェルプログラムを混同している
    Linuxはinitramfsやramdiskなしでもコンパイルでき、それでもファイルシステム上のユーザーランドを実行できる
    「Linux initrd interpreter」という表現は本当に不適切な説明だ

    • ELFファイルも、それ自体ではプログラムではない場合がある。ELFの一部は動的ライブラリであり、エントリポイントがないからだ。ELFの一部が実行可能であるように、CPIOの一部も実行可能だと見なせる。結局のところ、ld.soがELFをメモリに展開してエントリポイントを実行することと、カーネルがinitramfsを展開してエントリポイントを実行することは、似た概念だ
    • cpio内のinitファイルこそが実際に解釈されるプログラムであり、残りのファイルはそのプログラムが使うメモリの役割を果たす
    • バイナリプログラムはCPU上で実行されるが、プログラムファイル自体は複数のセクションから成るアーカイブ構造だ。CPUはプログラムファイルを直接理解できない。Linuxはプログラムが実行されるアドレス空間を設定し、その後プログラムカウンタが指すアドレスへジャンプする。ELFのメタデータセクションがこの過程を定義する
    • 少なくともAIが書いた文章ではないのが救いだ
  • すべてのOSはカーネル権限で動く機械語インタプリタの役割をしているのでは?

    • そうは思わない。OSは各命令を直接解釈せず、CPUに渡して実行させる
    • OSはシステム資源を利用できるようにするインターフェースだ。CPUが機械語を解釈し、OSはCPUに何を実行させるかを指示できる
    • この場合はCPIOファイル用のインタプリタと見なせる
  • この記事は「Linuxはインタプリタだ」というメンタルモデルとして見るなら問題ないが、文字どおりに受け取ると間違っている
    CPU命令レベルでの解釈ではなく、カーネルがELF、shebangスクリプト、initramfsのような実行形式を調整する役割だと見れば、より妥当だ。混乱は「インタプリタ」の二つの意味が混ざっていることに由来するようだ

  • 重要なのは比喩が正しいかどうかではなく、「実行」という概念がどれほど環境依存かを示している点だ

  • 「すべてはインタプリタだ?」

    • そうだが、コンパイラは例外だ
  • TuringのTheta Combinator

    • それがこの記事とどう関係するのかよく分からない。関数型プログラミングの概念に詳しくない
  • シリーズの以前の記事で、筆者はContaboのオブジェクトストレージを使いたくなかったので、自分でVPSイメージを作ったと言っていた
    月1.50ドルを節約するために50時間使うことと、25万ドルをトークンに使う極端さの間には、ちょうどよいバランスがあると思う。
    インフラ費用を賄えないのなら、技術力よりも社会的要因が問題なのかもしれない。Doomをcurlで動かすことに執着するのは生産的ではないと感じる

    • 自分も昔はそうだった。VPSの月5ユーロが高すぎて、お金がたまるまでインスタンスを停止し、ルートファイルシステムを母のノートPCにバックアップしていた。その後はKindleにTerminal IDEを入れて、busyboxとgccで遊んでいた。Spartacus Rexにはキャリアの出発点を与えてくれたことを感謝している
    • 筆者の言葉は冗談だった。実際の理由はすぐ次の段落にある — 「面白いトリックだと思ったし、ブログに載せれば自分も学べるし読者も学べるし、インターネット上のポイントも得られるwin-winだと思った」
    • 他人には非生産的に見えても、特別な関心事を楽しむことはメンタルヘルスに重要だ。ADHDの自分にはむしろ必要な活動だ
    • 「1.50ドル払えないならプロではない」という言い方はおかしい。プロフェッショナルとは報酬を受け取るかどうかで定義されるのであって、支出で定義されるものではない
  • man ld.soを見ると、ELFの.interpセクションに保存された動的リンカが実行されると明記されている。セクション名そのものが興味深い

  • Linuxはプログラム可能なインターフェースとして非常に有用だ。Windowsでも可能だが、Linuxのほうが向いていると感じる
    GUIはWindowsのほうがよいと思うが、GNOMEやKDEも使いづらい。だからfluxbox、icewm、ときにはxfceやmate-desktopを使っている。最近はシンプルで速い環境を好む。作業の大半はコマンドラインとコード編集でこなしている

    • 速くてシンプルな環境が欲しいなら、Sway + footの組み合わせがよい。キーバインドでワークスペースを構成すれば、デスクトップなしでも快適に使える
    • WindowsのGUIが優れているという点には同意できない。GNOMEやKDEもいまひとつだが、WindowsではMicrosoftの複雑なWMから逃れられない。個人的には、Xerox系よりもmpx/mux系インターフェース(例: 9wm, cwm, dwm)のほうがはるかによいと思う。Engelbartの哲学により近く、全体としてもっとすっきりしている