panic(9)でパニック を起こす
これまで2回に分け、Linuxカーネルをパニックさせる方法を紹介した。1回目はSysRqの仕組みでLinuxカーネルをパニックさせるという正規(?)の方法、2回目は機能を不適切に使ってLinuxカーネルをパニックさせる方法だった。今回はカーネルモジュールからpanic(9)をコールしてカーネルをパニックさせてみよう。
以前は、ほかにもLinuxカーネルをパニックさせる方法があったのだが、現在ではそのための穴がふさがっており、パニックを起こすことが不可能になっている。今回は別のアプローチでカーネルをパニックさせてみよう。
カーネル内部で使える関数にpanic(9)がある。これは文字通りカーネルをパニックさせる関数で、カーネル内部からこの関数を呼び出せばカーネルをパニックさせることができる。この関数はLinuxカーネルのみならず、UNIX系のカーネルには用意されていることが多いようだ。
カーネルの内部から実行するにはカーネルを書き換える必要があるが、カーネルモジュールにpanic(9)を仕込んでおけば似たようなことができる。
カーネルモジュールでゴー!
次のようなカーネルモジュールで十分だ。このファイルをpanic.cといった形でファイルに書いておく。
panic.c
#include <linux/module.h>
MODULE_LICENSE("BSD");
MODULE_AUTHOR("Daichi GOTO");
MODULE_DESCRIPTION("Panic module");
static int panic_init(void)
{
panic("panic module");
return 0;
}
static void panic_exit(void)
{
}
module_init(panic_init);
module_exit(panic_exit);
このカーネルモジュールをビルドするため、次のようなMakefileを用意しておく。
Makefile
obj-m= panic.o
all: build
build:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
rm -f *.o *.ko *.mod.c Module* module*
load: build
insmod panic.ko
unload:
rmmod panic
list:
lsmod
panic.cとMakefileは同じディレクトリに置いておく。make buildでコンパイルが実施され、make loadでシステムがパニックする。
make loadでinsmod panic.koというコマンドが実行され、panic.koというカーネルモジュールがカーネルに読み込まれる。読み込まれる段階でpanic("panic module")が実行され、カーネルがパニックすることになる。
カーネルモジュールはカーネルの内部で実行されるため、すぐにシステムをフリーズに至らすおかしな処理が可能だ。あまり作法を守らないで適当なコードを書いていると、愉快にカーネルを壊すことができる。もちろん実行しないに越したことはない。カーネルモジュールはそれだけ注意して書いておこうということだ。
頻繁に実行しないほうがよい
これまで2回にわたり、同じことを言っているが、今回もお伝えしておく。こうした処理は頻繁に実行しないほうがよい。シャットダウンの処理はshutdownコマンドなど、正規の方法で実施するようにしよう。パニック経由でシステムを終了すると、適切な終了処理が行われないことがあり、ファイルシステムなどに不整合が発生するおそれがあるのだ。