out of treeでライブパッチを試す、/dev/nullへのパッチ紹介

Linuxカーネルのバージョン4.0から追加されたライブパッチ(Livepatch)機能を今更ながら、試してみました。
(Linux4.0の記事でライブパッチに触れていますが、32bitのマシンしか無く、試せなかったんですね。。)


なお、本記事は「CLR/H #clrh101」のLTで発表させていただいた内容のまとめです。

この記事で行うこと

「ライブパッチとは何ぞや」はLinux4.0の記事で触れているので省略し、さっそく使ってみます。


Linuxカーネルソースコードに付属するサンプルをカーネルコンフィグで有効化し、
カーネルビルド時にビルドする」方法は、色々な記事で紹介されているので、
ここでは、
1. カーネルソースツリーの外(out of tree)で、ライブパッチのソースコード単体でビルド
2. 現在動作中のカーネルに再起動無しで、パッチを適用
を試してみます。
(といっても、単なるカーネルモジュールなので、
一般的な「out of treeでのビルド」と「insmod」という話です。)

0. Linuxカーネルのビルド・インストール・起動

ライブパッチに限らず、カーネルモジュールのビルド時、ビルド済のカーネルソースツリーを参照するので、
Linuxカーネルのビルドを行います。


また、カーネルモジュールはビルドしたカーネルと対応するので、
ビルドしたカーネルをインストール後、再起動します。


なお、前述の通りライブパッチはLinuxカーネルのバージョン4.0で追加された機能です。
Debian 8(Jessie)時点でLinuxカーネルのバージョンは3.16なので、
(少なくともDebianにおいて、Debianをお使いであれば、)
Linuxカーネルソースは本家であるThe Linux Kernel Archivesのものを使用すると良いです。


カーネルコンフィギュレーションやビルド・インストールについては、Linux4.0の記事を参考にしてください。

1. ライブパッチのビルド

ライブパッチのサンプルをout of treeビルドしてみます。


まず、作業ディレクトリ(livepatch-sample)を作成し、サンプルソースコードをコピー

[PC ~]$ mkdir livepatch-sample
[PC ~]$ cp linux-4.6.4/samples/livepatch/livepatch-sample.c livepatch-sample/


次に、以下の内容をMakefileというファイル名でlivepatch-sampleディレクトリに保存します。

obj-m = livepatch-sample.o

all:
	make -C $(KERNEL_SRC) M=$(PWD)

clean:
	make -C $(KERNEL_SRC) M=$(PWD) clean


livepatch-sampleへ移動し、以下のコマンドでビルドできます。
ビルドが完了すると"livepatch-sample.ko"というファイルができあがっています。

[PC ~]$ cd livepatch-sample
[PC ~/livepatch-sample]$ make KERNEL_SRC=../linux-4.6.4
・・・ビルドログ・・・
[PC ~/livepatch-sample]$ ls livepatch-sample.ko
livepatch-sample.ko

2. パッチの適用

これをinsmodでインストールすると、パッチを適用できます。
このパッチは、カーネルが生成している/proc/cmdlineの内容を変更するパッチなので、
パッチ適用前後に内容を確認します。

[PC ~/livepatch-sample]$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-4.6.4 root=UUID=e53154c7-c353-49e6-8ba7-9976df1e9ff9 ro quiet
[PC ~/livepatch-sample]$ sudo insmod livepatch-sample.ko
[PC ~/livepatch-sample]$ cat /proc/cmdline
this has been live patched


なお、/var/log/messagesを確認すると、insmod時に以下のログが出ています。

Jul 24 17:13:20 seven kernel: [ 275.460680] livepatch: tainting kernel with TAINT_LIVEPATCH
Jul 24 17:13:20 seven kernel: [ 275.460683] livepatch: enabling patch 'livepatch_sample'

"taint"は「汚れる」といった意味で、「ライブパッチによりカーネルを汚した」といったことを意味しています。
ライブパッチ機能によりソースコードが公開されていないバイナリをカーネルに適用する可能性もあるので、
バグレポートなどの際に、カーネル開発者がログから「汚されていないか」を確認する意味があります。

補足: /dev/null へのパッチ

CLR/H #clrh101」のLTの最後に紹介した
「/dev/nullをreadするとメッセージを出力する」パッチはGitHubの以下の場所にpushしました。

使い方などは、上記URL先のREADMEをご覧ください。