Ubuntu Weekly Topicsの2016年10月21日号でも伝えているように、
「Canonical Livepatch Service」とは
「Canonical Livepatch Service」CONFIG_
を使っています。
カーネルのLivepatch機能とサービス側の都合により、
- Intel/
AMDの64ビットアーキテクチャ (amd64) のみ - Ubuntu 16.
04 LTSの公式カーネル (Linux 4. 4) のみ - Ubuntuカーネルでいうところのgenericフレーバーとlow latencyフレーバーのみ
- Ubuntu 16.
04 LTSから標準でインストールされるようになったsnapdの2. 15以降が必要 - Canonical Livepatch Serviceサイト
(https:// livepatch. canonical. com:443) へのアクセス - Ubuntu Single Sign Onアカウント
(Launchpadなどのアカウント)
snapdが必要なのは、
Livepatchクライアントは、
またセキュリティパッチそのものは、sudo apt update && sudo apt upgrade
」
Livepatch Serviceを使ってみる
まずはLivepatch Serviceをそのまま使ってみましょう。3台までならUbuntu Advantageを購入しなくても利用できます。あらかじめUbuntu Livepatch Serviceのサイトから、
![画像](/assets/images/admin/serial/01/ubuntu-recipe/0443/thumb/TH800_01.png)
![画像](/assets/images/admin/serial/01/ubuntu-recipe/0443/thumb/TH800_02.png)
次にsnap
コマンドを使ってクライアントをインストールします。
$ snap find livepatch Name Version Developer Notes Summary canonical-livepatch 5 canonical - Canonical Livepatch Client $ sudo snap install canonical-livepatch (中略) $ snap list Name Version Rev Developer Notes canonical-livepatch 5 15 canonical - ubuntu-core 16.04.1 423 canonical -
snap
はUbuntu 16.
さて、/snap
ディレクトリ以下に保存されます。
$ ls /snap/ bin canonical-livepatch ubuntu-core $ ls /snap/canonical-livepatch/current/ canonical-livepatch command-canonical-livepatchd.wrapper etc meta usr canonical-livepatchd command-canonical-livepatch.wrapper keys sbin $ ps -fe | grep livepatch root 1545 1 0 20:05 ? 00:00 /snap/canonical-livepatch/15/canonical-livepatchd shibata 1587 1217 0 20:05 pts/25 00:00 grep --color=auto livepatch
canonical-livepatchをインストールすると、canonical-livepatchd
が立ち上がります。またcanonical-livepatch
コマンドを使ってこのデーモンと通信することになります。ちなみに、
Livepatch Serviceの初期設定
Livepatch Serviceを使うためには、
Livepatch Serviceでは/var/
ファイルを作成してください。
http-proxy: "http://proxy.example.co.jp:8080"
https-proxy: "https://proxy.example.co.jp:8080"
no-proxy: "example.co.jp"
設定を行ったら、canonical-livepatchd
サービスを再起動します。
$ sudo systemctl restart snap.canonical-livepatch.canonical-livepatchd.service
Livepatch Serviceではカーネルモジュールをダウンロードしてカーネルに取り込みます。セキュアブート環境においてはロードするカーネルモジュールも検証の対象になります。つまりこのモジュールの署名検証用の証明書をあらかじめ取り込んでおく必要があります。セキュアブート環境はまず、
$ sudo mokutil --import /snap/canonical-livepatch/current/keys/livepatch-kmod.x509
Livepatch Serviceを有効化する
一通りの設定が終わったら、canonical-livepatch
コマンドで、
$ sudo canonical-livepatch enable トークン Successfully enabled device. Using machine token: マシントークン $ canonical-livepatch status --verbose client-version: "5" machine-id: マシンID machine-token: マシントークン architecture: x86_64 cpu-model: Intel Xeon E3-12xx v2 (Ivy Bridge) last-check: 2016-10-22T20:08:49.442817865+09:00 boot-time: 2016-10-22T19:43:15+09:00 uptime: 27m20s status: - kernel: 4.4.0-45.66-generic running: true livepatch: state: nothing-to-apply version: "" fixes: ""
status
サブコマンドを実行すると、
$ sudo apt install linux-image-4.4.0-43-generic linux-image-extra-4.4.0-43-generic
再起動するときにGRUBの画面でstatus
サブコマンドを実行します。
$ uname -a Linux ubuntu-desktop 4.4.0-43-generic #63-Ubuntu SMP Wed Oct 12 13:48:03 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux $ canonical-livepatch status --verbose client-version: "5" machine-id: マシンID machine-token: マシントークン architecture: x86_64 cpu-model: Intel Xeon E3-12xx v2 (Ivy Bridge) last-check: 2016-10-22T20:30:04.652+09:00 boot-time: 2016-10-22T20:29:30+09:00 uptime: 45s status: - kernel: 4.4.0-43.63-generic running: true livepatch: state: applied version: "13.3" fixes: '* CVE-2016-5195 LP: #1633547'
どうやらCVE-2016-5195対応のパッチが適用されているようです。実際にlsmod
を実行すると、
$ lsmod | grep livepatch kpatch_livepatch_Ubuntu_4_4_0_43_63_generic_13 16384 1
カーネルモジュールは/var/
以下にダウンロードされます。
$ sudo ls /var/snap/canonical-livepatch/common/payload/ changelog copyright cvelist.yaml livepatch_Ubuntu_4_4_0_63_generic_13.ko meta
Dirty COW対応を検証する
CVE-2016-5195はいわゆるdirtyc0w.
を試してみましょう。
$ wget https://raw.githubusercontent.com/dirtycow/dirtycow.github.io/master/dirtyc0w.c $ sudo -s $ echo this is not a test | sudo tee foo $ sudo chown root: foo $ sudo chmod 0404 foo $ ls -lah foo -r-----r-- 1 root root 19 Oct 22 18:03 foo $ cat foo this is not a test $ gcc -pthread dirtyc0w.c -o dirtyc0w $ ./dirtyc0w foo m00000000000000000 mmap 7f3cf7423000 madvise 0 procselfmem 1800000000 $ cat foo this is not a test
dirtyc0w
コマンドは、mmap()
し2つのスレッドを立ち上げ、/proc/
経由でmmap()
したアドレスに書き込みを行い、madvice()
にmmap()
したアドレスとMADV_
を渡し続けるというコードです。いずれも1億回同じ処理を繰り返すことで、
脆弱性の存在するはずの4.foo
ファイルの内容は書き換えられていません。これがLivepatch Service導入前であれば、foo
の内容がdirtyc0w
コマンドに渡したm00000000000000000
になってしまいます。
Livepatch Serviceを無効化する
現在のところ、rmmod
コマンドもエラーとなります。
$ sudo rmmod kpatch_livepatch_Ubuntu_4_4_0_43_63_generic_13 rmmod: ERROR: Module kpatch_livepatch_Ubuntu_4_4_0_43_63_generic_13 is in use
現時点で無効化する唯一の方法は、canonical-livepatch
コマンドからCanonical Livepatchのサービスそのものを停止することです。
$ sudo canonical-livepatch disable Successfully disabled device. Removed machine-token: マシントークン
この状態で再起動すると、
当然のことながらsudo apt update && sudo apt upgrade
」
自分でLivepatchモジュールをビルドしてみる
Livepatch機能そのものはオリジナルのカーネルに存在する機能です。このため、
特定の関数をフックするモジュール
Livepatch機能はカーネルの関数トレーシング機能CONFIG_
)fs/
のcmdline_
をフックするlivepatch-sample.
が存在します。cmdline_
をフックすれば、/proc/
の出力結果を変更できます。
そこでこのサンプルコードをビルドしてみましょう。まずカーネルモジュールのビルドのために、
$ sudo apt install linux-headers-`uname -r` $ sudo apt build-dep linux $ mkdir livepatch && cd $_ $ wget http://kernel.ubuntu.com/git/ubuntu/ubuntu-xenial.git/plain/samples/livepatch/livepatch-sample.c
モジュールビルド用にKbuildとMakefileを作りましょう。
(Kbuildの内容)
obj-m := livepatch-sample.o
(Makefileの内容)
KDIR ?= /lib/modules/`uname -r`/build
default:
$(MAKE) -C $(KDIR) M=$$PWD
あとはmake
するだけです。
$ make $ ls Kbuild Module.symvers livepatch-sample.c livepatch-sample.mod.c livepatch-sample.o Makefile built-in.o livepatch-sample.ko livepatch-sample.mod.o modules.order
ビルドしたlivepatch-sample.
をロードして、/proc/
の結果を比較してみましょう。
$ cat /proc/cmdline BOOT_IMAGE=/boot/vmlinuz-4.4.0-43-generic.efi.signed (略) $ sudo insmod livepatch-sample.ko $ cat /proc/cmdline this has been live patched $ echo 0 | sudo tee /sys/kernel/livepatch/livepatch_sample/enable $ cat /proc/cmdline BOOT_IMAGE=/boot/vmlinuz-4.4.0-43-generic.efi.signed (略)
/proc/
の出力結果がlivepatch-sample.
で指定した/proc/
の出力結果も元に戻っています
差分ファイルからパッチモジュールを作る
前項では特定の関数を完全に置き換えるパッチモジュールを作成しました。しかしながら脆弱性対応という観点から言えば、
kpatchの一部であるkpatch-buildをインストールすれば、
$ sudo apt build-dep linux $ sudo apt install kpatch-build $ git clone https://git.launchpad.net/~ubuntu-livepatch/+git/xenial-livepatches $ cd xeinali-livepatches/Ubuntu-4.4.0-43.63 $ cp Ubuntu-4.4.0-43.63.diff livepatch-Ubuntu-4.4.0-43.63-generic_13.diff
kpatch-build
コマンドは内部でカーネルをビルドするため、commit:fa0c02eb4
」
あとはmake
を実行すれば、kpatch-build
を実行してくれます。かなり時間がかかりますので、
$ make dget -u https://launchpad.net/ubuntu/+archive/primary/+files/linux_4.4.0-43.63.dsc (中略) wget -q https://launchpad.net/ubuntu/+archive/primary/+files/linux-image-4.4.0-43-generic-dbgsym_4.4.0-43.63_amd64.ddeb (中略) + rm -rf /tmp/tmp.NlCVnRvZeW/buildroot + unset KCFLAGS echo "Build complete for 4.4.0-43.63 generic amd64 revision 13" Build complete for 4.4.0-43.63 generic amd64 revision 13 $ ls Makefile linux-image-4.4.0-43-generic-dbgsym_4.4.0-43.63_amd64.ddeb livepatch-Ubuntu-4.4.0-43.63-generic_13.diff Ubuntu-4.4.0-43.63.diff linux_4.4.0-43.63.diff.gz livepatch_Ubuntu_4_4_0_43_63_generic_13.ko linux-4.4.0 linux_4.4.0-43.63.dsc vmlinux linux-4.4.0.config linux_4.4.0.orig.tar.gz
上記のうちlivepatch_
が、