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コマンドなど、正規の方法で実施するようにしよう。パニック経由でシステムを終了すると、適切な終了処理が行われないことがあり、ファイルシステムなどに不整合が発生するおそれがあるのだ。