自作カーネルモジュールでパニックを起こしてみる

Linux カーネルとお友達になるべく、カーネルモジュールを書いてみました。

## カーネルモジュール作成
まずはカーネルモジュールを書く。
以下のサイト様を参考にさせていただきました。

  http://taltalp.hatenablog.jp/entry/2016/09/04/182426
  http://www.mech.tohoku-gakuin.ac.jp/rde/contents/linux/drivers/module.html


### 手順
1. yum install kernel-devel

2. vim my_module.c

　露骨なアクセス違反プログラムを書いてみる

```
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>

int init_module(){
    int i[10];
    // アクセス違反を起こす
    printk(KERN_INFO "my bad access: address %p : data %d\n", &(i[4096]), i[4096]);
    printk(KERN_INFO "my bad access: address %p : data %d\n", &(i[i[4096]]), i[i[4096]]);
    printk(KERN_INFO "my module is loaded at %lu\n", jiffies);
    return 0;
}

void cleanup_module(){
    printk(KERN_INFO "my module is unloaded at %lu\n", jiffies);
}
```


3. vim Makefile

```
obj-m := my_module.o

all:
                make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
                make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
```


4. make all

make コマンドで出力された my_module.ko がカーネルモジュールの実行ファイルである。

## モジュールロード

下記コマンドでモジュールをロードする


```
# insmod my_module.ko
```

上記自作モジュールをロードしたとき、パニックする場合としない場合がある。
普通のユーザアプリケーションならセグメンテーションフォールトで即刻落ちるプログラムだが、
カーネルにはセグメンテーションはないらしい。
（カーネルがユーザアプリケーションに対してセグメンテーションを与えているのだから当たり前か）

### パニックしない場合

ロードできた


```
# lsmod | grep my_module
my_module              12426  0
```


dmesg に printk() で出力したメッセージが確認できる

```
[  795.109515] my bad access: address ffff880036207d28 : data 17300
[  795.109550] my bad access: address ffff880036214b78 : data 0
[  795.109579] my module is loaded at 4295462624
```


### パニックする場合

パニックし kdump により vmcore が吐かれた
vmcore-dmesg 曰く paging 関係でエラーらしい。


```
      :
[  936.317621] BUG: unable to handle kernel paging request at ffff880264771b28
[  936.317662] IP: [<ffffffffa05db043>] init_module+0x43/0x90 [my_module]
      :
```


crash で tainted module を見る。
当たり前だが、ちゃんと tainted module として表示される。

```
crash> mod -t
NAME       TAINTS
my_module  POE
```


バックトレースを見る。
do_one_initcall() 中でページフォールトして死んでいることが良くわかる。

```
crash> bt
PID: 7818   TASK: ffff880064089700  CPU: 0   COMMAND: "insmod"
 #0 [ffff88006571f9f0] machine_kexec at ffffffff81051beb
 #1 [ffff88006571fa50] crash_kexec at ffffffff810f2542
 #2 [ffff88006571fb20] oops_end at ffffffff8163e1a8
 #3 [ffff88006571fb48] no_context at ffffffff8162e2b8
 #4 [ffff88006571fb98] __bad_area_nosemaphore at ffffffff8162e34e
 #5 [ffff88006571fbe0] bad_area_nosemaphore at ffffffff8162e4b8
 #6 [ffff88006571fbf0] __do_page_fault at ffffffff81640fce
 #7 [ffff88006571fc48] do_page_fault at ffffffff81641113
 #8 [ffff88006571fc70] page_fault at ffffffff8163d408
    [exception RIP: init_module+67]
    RIP: ffffffffa05db043  RSP: ffff88006571fd28  RFLAGS: 00010246
    RAX: 000000007fc14780  RBX: ffffffff81951020  RCX: 0000000000000000
    RDX: 0000000000000000  RSI: ffff88007fc0d6c8  RDI: ffffffffa05dc028
    RBP: ffff88006571fd58   R8: 0000000000000086   R9: 0000000000000618
    R10: 0000000000000082  R11: 0000000000000000  R12: ffff88007959cd40
    R13: ffffffffa05db000  R14: 0000000000000000  R15: ffffffffa05dd000
    ORIG_RAX: ffffffffffffffff  CS: 0010  SS: 0018
 #9 [ffff88006571fd60] do_one_initcall at ffffffff810020e8
#10 [ffff88006571fd90] load_module at ffffffff810ed4ae
#11 [ffff88006571fee8] sys_finit_module at ffffffff810ede66
#12 [ffff88006571ff80] system_call_fastpath at ffffffff81645909
    RIP: 00007f8576725949  RSP: 00007ffd968eae08  RFLAGS: 00010246
    RAX: 0000000000000139  RBX: ffffffff81645909  RCX: 000000000000001f
    RDX: 0000000000000000  RSI: 000000000041a13c  RDI: 0000000000000003
    RBP: 000000000041a13c   R8: 0000000000000000   R9: 00007ffd968eb018
    R10: 0000000000000003  R11: 0000000000000206  R12: 0000000000000000
    R13: 000000000097e130  R14: 0000000000000000  R15: 000000000097f1f0
    ORIG_RAX: 0000000000000139  CS: 0033  SS: 002b
```

page fault 時の動作は以下が詳しい。
https://wiki.bit-hive.com/linuxkernelmemo/pg/%E3%83%9A%E3%83%BC%E3%82%B8%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88

アクセスした仮想メモリアドレスにマッピングする物理メモリが存在しなかった場合に page fault となる。