本当は必要なかったWSLカーネルのセルフビルド(ip_tablesモジュール)

Posted by 雅楽斎 on Wednesday, April 26, 2023

TOC

この記事の作業をするに至った経緯

  • MicrosoftがビルドしているWSLのカーネルは動的にロードするカーネルモジュールを一切使わずに全てカーネルの中に入っている
  • Rootless Dockerはインストーラーの中でip_tablesモジュールをmodprobeするが、WSLのカーネルはip_tablesモジュールがカーネルモジュールとして存在しないのでエラーになる(無視して進むオプションはある)
  • MicrosoftがビルドしているWSLのカーネルはGitHubで公開されているので、ip_tablesをモジュールとしてコンパイルしたカーネルと差し替えればRootless Dockerのインストーラーでエラーメッセージも出ないし解決法としてスマートに思えた
  • 実際にWSLのカーネルをセルフビルドしたらip_tablesは確かにモジュールにできたけど最初からip_tablesはカーネルの中でビルド対象になっていたので、わざわざセルフビルドした意味はなかった
  • 一応WSLのカーネルを差し替えて動くことは確認したので、いつ使うかは不明だけど知見は得られた

WSLのカーネルを差し替えるのに必要なもの

  • セルフビルドしたvmlinux
  • WSLを実行するWindowsユーザーのホームディレクトリにある.wslconfigの書き換え

WSL2上でRootless Dockerのインストールで表示されるメッセージ(再掲)

詳細は以下の記事に記載したとおりですが、WSL2上でRootless Dockerのインストーラーを実行するとこんなメッセージが表示されます。

WSL2でRootless Docker

$ dockerd-rootless-setuptool.sh install
[ERROR] Missing system requirements. Run the following commands to
[ERROR] install the requirements and run this tool again.
[ERROR] Alternatively iptables checks can be disabled with --skip-iptables .

########## BEGIN ##########
sudo sh -eux <<EOF
# Load ip_tables module
modprobe ip_tables
EOF
########## END ##########

modprobeができないけども、このチェックをせずに進めるなら--skip-iptablesをつけてね、というものです。ちなみに、手でmodprobeしてもできません。カーネルモジュールのあるべきディレクトリがそもそも存在しないこともわかります。

$ modprobe ip_tables
modprobe: FATAL: Module ip_tables not found in directory /lib/modules/5.15.90.1-microsoft-standard-WSL2
$ file /lib/modules/5.15.90.1-microsoft-standard-WSL2
/lib/modules/5.15.90.1-microsoft-standard-WSL2: cannot open `/lib/modules/5.15.90.1-microsoft-standard-WSL2' (No such file or directory)

で、まだWSL上でsystemdを使えなかった時に書かれたこちらのブログでカーネルのセルフビルド手順が書かれていたので、丸っきりなぞりました。

WSL 2にip_tables.koカーネルモジュールを入れる方法 - チラシの裏からうっすら見える外枠の外のメモ書き

カーネルソースコードの取得とビルド

必要なパッケージのインストール

カーネルのビルドに必要なパッケージをインストールします。

# apt-get install build-essential flex bison libssl-dev libelf-dev libncurses-dev autoconf libudev-dev libtool dwarves

なお、dwarvesは参考サイトには書かれていませんでしたが入れないとリンクに失敗するのでインストールしました。

  LD      vmlinux.o
  MODPOST vmlinux.symvers
  MODINFO modules.builtin.modinfo
  GEN     modules.builtin
BTF: .tmp_vmlinux.btf: pahole (pahole) is not available
Failed to generate BTF for vmlinux
Try to disable CONFIG_DEBUG_INFO_BTF
make: *** [Makefile:1218: vmlinux] エラー 1

compilation - BTF: .tmp_vmlinux.btf: pahole (pahole) is not available - Stack Overflow

対象のカーネルバージョンを確認

今のカーネルと極力同じカーネルを使うので(余計なバグを持ってきたくないので)、まずは現在のWSL2のカーネルを確認します。

$ uname -a
Linux DESKTOP-8KGOMCC 5.15.90.1-microsoft-standard-WSL2 #1 SMP Fri Jan 27 02:56:13 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

ということで、5.15.90.1-microsoft-standard-WSL2のカーネルのソースをgithubから持ってきます。

ブランチも確認

GitHub上のカーネルの5.15.90,1に一番近いものを確認します。今回はlinux-msft-wsl-5.15.yが一番近いので、デフォルトでも大丈夫です。

GitHub - microsoft/WSL2-Linux-Kernel: The source for the Linux kernel used in Windows Subsystem for Linux 2 (WSL2)

ここからはrootユーザーで作業する方が楽なので、sudo -iでrootユーザーになったら、gitリポジトリのクローンとブランチの切り替えをします。

# git clone https://github.com/microsoft/WSL2-Linux-Kernel.git /usr/src/5.15.90.1-microsoft-standard-WSL2 -b linux-msft-wsl-5.15.y --depth 1

指定している引数は以下の通りです。

  • https://github.com/microsoft/WSL2-Linux-Kernel.git gitリポジトリ
  • /usr/src/5.15.90.1-microsoft-standard-WSL2 clone先(/usr/src/unameで表示されたカーネルのバージョン)
  • -b linux-msft-wsl-5.15.y ブランチとしてlinux-msft-wsl-5.15.yを指定
  • –depth 1 最新ファイルだけをcloneする(git pushをしない前提で通信量を削減)

現在作業しているブランチを確認します(今回はデフォルトなので心配は不要ですが)

# cd /usr/src/5.15.90.1-microsoft-standard-WSL2/
# git branch --contains
* linux-msft-wsl-5.15.y

現在動作しているカーネルのconfigを反映する

# pwd
/usr/src/5.15.90.1-microsoft-standard-WSL2
# cp /proc/config.gz ./
# gunzip config.gz
# mv config .config

ビルドするモジュールを指定する

# make menuconfig

ncursesによるビルドモジュールの指定画面が出るので、指定します。

Networking supportNetworking optionsNetwork packet filtering framework (Netfilter)IP: Netfilter ConfigurationIP tables support (required for filtering/masq/NAT)をMにしてカーネルモジュールとしてビルドするようにEnterで切り替えるのですが。

カーネルに含めてビルドする設定になってるやんけ!

で、今回はここまで辿ってしまったので一旦モジュールとしてビルドすることにして先に進みます。

ここでOkを選択すると.configが更新されて、ビルド時に設定が参照されるということになっています。

カーネルのビルド

いよいよカーネルをビルドします。-jに指定する4は私の理解では論理コア数をそのまま指定すれば問題ないと思うので指定しています。

# make -j 4 && make modules_install -j 4 && make install -j 4
(snip)
  CALL    scripts/atomic/check-atomics.sh
  INSTALL /lib/modules/5.15.90.1-microsoft-standard-WSL2+/kernel/net/ipv4/netfilter/iptable_security.ko
  DEPMOD  /lib/modules/5.15.90.1-microsoft-standard-WSL2+
arch/x86/Makefile:142: CONFIG_X86_X32 enabled but no binutils support
sh ./arch/x86/boot/install.sh 5.15.90.1-microsoft-standard-WSL2+ \
        arch/x86/boot/bzImage System.map "/boot"
run-parts: executing /etc/kernel/postinst.d/unattended-upgrades 5.15.90.1-microsoft-standard-WSL2+ /boot/vmlinuz-5.15.90.1-microsoft-standard-WSL2+

今回、dwarvesパッケージがないせいでリンクに失敗したので厳密な時間計測はできませんでしたが、SSDに換装したRAM 16GBのThinkPad X270で25分くらいでした。25分でカーネルがビルドできるとかすごい時代になったものです。(2時間くらいかかると思って席を外していた人並みの感想)

生成物はこんな感じです。

-rw-r--r--   1 root root 947034264  4月 23 13:50 vmlinux.o
-rw-r--r--   1 root root    632832  4月 23 13:50 vmlinux.symvers
-rw-r--r--   1 root root    113824  4月 23 13:50 modules.builtin.modinfo
-rw-r--r--   1 root root     14931  4月 23 13:50 modules.builtin
-rwxr-xr-x   1 root root 833605488  4月 23 13:52 vmlinux
-rw-r--r--   1 root root   6213612  4月 23 13:52 System.map
-rw-r--r--   1 root root       391  4月 23 13:52 modules-only.symvers
-rw-r--r--   1 root root    633223  4月 23 13:52 Module.symvers
drwxr-xr-x  26 root root      4096  4月 23 13:52 arch

この833MBあるvmlinuxをWSLカーネルとして使います。

カーネルの差し替え

カーネルをrootユーザーでビルドしたので、一旦ファイルを一般ユーザーで触れる場所に移動します。

# mv /usr/src/5.15.90.1-microsoft-standard-WSL2/vmlinux /mnt/c/Users/hogehoge/

エクスプローラーでユーザーのホームディレクトリにWslCustomKernelというディレクトリを作って、そこにvmlinuxを入れることにします。入れたら、ホームディレクトリに.wslconfigというファイルが(なければ)作成し、以下の記述を追加します。

[wsl2]
kernel=C:\\Users\\hogehoge\\WslCustomKernel\\vmlinux

コマンドプロンプトor PowerShellで以下のコマンドを実行して、実行中のWSLを終了します。

> wsl --shutdown

適当にWSLを起動して、カーネルを確認します。

$ uname -a
Linux DESKTOP-8KGOMCC 5.15.90.1-microsoft-standard-WSL2+ #2 SMP Sun Apr 23 13:50:29 JST 2023 x86_64 x86_64 x86_64 GNU/Linux

カーネルが5.15.90.1-microsoft-standard-WSL2+に変わりました。

一応ip_tablesモジュールがあることを確認します。

$ lsmod
Module                  Size  Used by
ip_tables              24576  0
$ ls /lib/modules/5.15.90.1-microsoft-standard-WSL2+/
build              modules.builtin            modules.dep      modules.softdep
kernel             modules.builtin.alias.bin  modules.dep.bin  modules.symbols
modules.alias      modules.builtin.bin        modules.devname  modules.symbols.bin
modules.alias.bin  modules.builtin.modinfo    modules.order    source

ということでカーネルのセルフビルドと差し替えを確認しました。

スポンサーリンク


comments powered by Disqus