SIer だけど技術やりたいブログ

動的リンク vs 静的リンク

linux

動的リンク、静的リンクとは

動的リンク(ダイナミックリンク)と静的リンク(スタティックリンク)という言葉がある。簡単にいうと、

  • 動的リンクは、バイナリに必要なライブラリを実行時にリンクするもの。
  • 静的リンクは、バイナリに必要なライブラリをコンパイル時にバイナリに入れ込むもの。

参考 C言語がコンパイル~実行されるまで

動的リンクは、ライブラリのバージョンを上げれば、それを利用しているソフトウェアの全てが更新される。そのため、バグや脆弱性対応の観点からは望ましいとされている。 しかしライブラリが勝手に更新されるわけで、それでもそれぞれのソフトウェアが動作するためには、様々なソフトウェアが利用するライブラリの互換性をディストリビューション内できちんと管理しながら開発する必要があり(互換性を切るなら切るで libc.so.1 -> libc.so. 2のようにインクリメントする)、提供難易度が高い。

静的リンクは、必要なライブラリがバイナリに入れ込まれているため、 利用したいライブラリのバージョンは各ツールが勝手に上げられる。 一方でバグや脆弱性の対応で一部のライブラリの更新が必要になると、すべての利用者が再ビルドする必要がある。

動的リンクと静的リンク、どちらが多いか

Amazon Linux 2023 AMI(al2023-ami-2023.1.20230705.0-kernel-6.1-x86_64)で、ルートから全ファイルに file コマンドかけて測定した。

その結果、動的リンク(1716件)、静的リンク(3件)で動的リンクが圧勝だった

# find / | xargs -I @@ file @@ > file.log

# cat file.log | grep "statically linked" | wc -l
3

# cat file.log | grep "dynamically linked" | wc -l
1716

静的リンクが増えてる気がする

ディストリビューションが提供するパッケージは動的リンクが多いとしても、最近 Kubernetes やら周辺ツールの調査をしてると、シングルバイナリのツールが増えてきたよな、と感じる。 それは、次のような理由からだと思う。

  • Kubernetes 関連のソフトウェアが Golang で書かれることが多いため
    • たとえば kubeadm や kubectl や runc
    • シングルバイナリなら、様々なディストリビューションに提供するコストを下げられるメリットもある
  • コンテナイメージを軽量化する手段としてシングルバイナリが流行ってるため

でもよく考えると、こういったシングルバイナリを作るためには特定のディストリビューションでビルドしているわけで、モノによっては特定のディストリビューションのライブラリが静的リンクされている可能性もあるわけで、ということは、適切に脆弱性情報を収集してパッチ当てるのが必要なんだよな、と思ったわけでした。適当にインストールしてきたそのシングルバイナリ、下回りの脆弱性が見つかったときにどう更新しますか?みたいなことは考えたほうが良さげ。静的リンクは、ディストリビュータのライブラリ更新作業の恩恵には預かれないのだ…。

とくに runc は Github の Release から取れるやつは Ubuntu 上で静的リンクされてるが、docker.ioから提供されたやつじゃなくていいの?みたいな話はあって、Release Notesでディストリビューションから提供されてるやつ使ったほうがいいよ、と推奨されていた。自分で作成したシングルバイナリonコンテナなら、脆弱性情報を収集するために trivy で定期的にスキャンしたりするんでしょう…知らんけど。