linuxカーネルパッチ:Known exploit detectionで遊んでみる

2013年12月中頃のLWNの記事で Known-exploit detection for the kernel というのがちょっと気になったので試してみた。

今の時点(2014/01/21)だとlinux-nextのtreeにも入っていないので今後どうなるかはわかりませんが。。。 記事の時点で投稿されたパッチは全部で9個でそのうち1、2番目が機能に関する部分で3~9がexploitの検出をしているパッチ。

さて、exploitの検出といってもこの機能を使えば自動的に検出をしてくれる訳ではなくて、そこは自分で書く必要があるという感じですね。 例えば[PATCH 4/9] net: Known exploit detection for CVE-2012-2136だとこのように。

-    if (npages > MAX_SKB_FRAGS)
+   if (npages > MAX_SKB_FRAGS) {
+       exploit("CVE-2012-2136");
        goto failure;
+   }

では実際にカーネルにパッチを当てて遊んでみる。パッチは1番目と2番目の機能に関するものだけ当てる。各ページにあるリンクの[Download message RAW]からメールが取得できるのでcurlで適当にダウンロード&保存してgit amでパッチ当ててカーネルコンパイル。これでexploit検出機能は使えるようになったので簡単なテストコードを書いて実行。

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/exploit.h>

MODULE_DESCRIPTION("exploit detection test module");
MODULE_AUTHOR("masami256");
MODULE_LICENSE("GPL");

static int test_value = 0;
module_param(test_value, int, 0644);

static int
exploit_test_init(void)
{
        pr_info("module loaded with test_value %d\n", test_value);
        exploit_on(test_value > 100, "TEST_0123_4567");

        return 0;
}

static void
exploit_test_cleanup(void)
{
        pr_info("module unloaded\n");
}

module_init(exploit_test_init);
module_exit(exploit_test_cleanup);

まずはパラメータに100を渡した場合。

masami@kerntest:~/exploit_detetcion_test$ sudo insmod ./exploit_test.ko test_value=100
masami@kerntest:~/exploit_detetcion_test$ dmesg
[ 2840.412098] module loaded with test_value 100

当然何も起きずにモジュールのロードに成功する。 次に101を渡す。

masami@kerntest:~/exploit_detetcion_test$ sudo insmod ./exploit_test.ko test_value=101
masami@kerntest:~/exploit_detetcion_test$ dmesg
[ 2840.412098] module loaded with test_value 100
[ 2851.139702] module unloaded
[ 2853.591675] module loaded with test_value 101
[ 2853.591698] type=1703 audit(1390279872.706:7): exploit id=TEST_0123_4567 pid=1187 uid=0 auid=1000 ses=1 comm="insmod"
[ 2853.591701] warning: possible TEST_0123_4567 exploit attempt by pid=1187 uid=0 comm=insmod

下の2行がeploit検出時のログ。 一番下の「warning: possible~」は_expolit()の中でprintk()で表示している箇所で、その上の行はaudit機能が有効な場合のログです。

もしexploitのチェックに引っかかった時に何かしたい場合はexploit_on()ではなくてチェックをした後にexploit()を呼ぶという使い方になる。

    if (test_value > 100) {
        exploit("TEST_0123_4567");
        // 何か処理する
    }

たのしいバイナリの歩き方

たのしいバイナリの歩き方