vxlinux

linux のシステムコールをフックする (DSAS開発者の部屋 2008-07-25)というエントリがあったので、そんなときこそ、vxlinuxと思って試してみたけど、結論から言うとうまく動かすことができなった。
環境はCentOS 5/IA32。binutils/gcc共にソースからコンパイル
sandboxing環境で実行できるのは静的リンクでコンパイルされた実行バイナリだけなので(Plan9の場合はそれで十分だが)、同梱されているラッパスクリプトvxlinuxgccを使う。

実行結果は次のように、glibcのdouble free checkで引っかかっている。

$ ./hello 
cd /opt/vx32-0.12/src/vxlinux
vxlinux /opt/vx32-0.12/src/vxlinux/_hello
eax 00000000  ecx 00000000  edx 00000000  ebx 00000000
esp 080475d0  ebp 00000000  esi 00000000  edi 00000000
eip 08048110  eflags 00000000
*** glibc detected *** ./vxlinux: double free or corruption (fasttop): 0x09673288 ***
======= Backtrace: =========
/lib/libc.so.6[0x700b16]
/lib/libc.so.6(cfree+0x90)[0x704070]
./vxlinux[0x80493fa]
/lib/libc.so.6(__libc_start_main+0xdc)[0x6addec]
./vxlinux[0x8048a51]
======= Memory map: ========
00110000-00113000 rwxp 00110000 00:00 0 
0027e000-0037e000 rwxp 0027e000 00:00 0 
0067a000-00694000 r-xp 00000000 08:03 28049417   /lib/ld-2.5.so
00694000-00695000 r-xp 00019000 08:03 28049417   /lib/ld-2.5.so
00695000-00696000 rwxp 0001a000 08:03 28049417   /lib/ld-2.5.so
00698000-007d5000 r-xp 00000000 08:03 28049419   /lib/libc-2.5.so
007d5000-007d7000 r-xp 0013c000 08:03 28049419   /lib/libc-2.5.so
007d7000-007d8000 rwxp 0013e000 08:03 28049419   /lib/libc-2.5.so
007d8000-007db000 rwxp 007d8000 00:00 0 00e97000-00e98000 r-xp 
00e97000 00:00 0          [vdso]
047f7000-04802000 r-xp 00000000 08:03 28049477   /lib/libgcc_s-4.1.2-20080102.so.1
04802000-04803000 rwxp 0000a000 08:03 28049477   /lib/libgcc_s-4.1.2-20080102.so.1
08048000-08054000 r-xp 00000000 08:03 2032967    /opt/vx32-0.12/src/vxlinux/vxlinux
08054000-08059000 rwxp 0000b000 08:03 2032967    /opt/vx32-0.12/src/vxlinux/vxlinux
0966b000-0968c000 rwxp 0966b000 00:00 0 
b7e00000-b7e21000 rwxp b7e00000 00:00 0 
b7e21000-b7f00000 --xp b7e21000 00:00 0 
bf867000-bf87d000 rwxp bf867000 00:00 0          
[stack]
zsh: abort (core dumped)  ./hello

チェックを無効にしても、trap 0xe ページフォルト?でエラー終了する。
う〜む。

$ MALLOC_CHECK_=0 ./hello
cd /opt/vx32-0.12/src/vxlinuxvxlinux /opt/vx32-0.12/src/vxlinux/_hello
eax 00000000  ecx 00000000  edx 00000000  ebx 00000000
esp 080475bc  ebp 00000000  esi 00000000  edi 00000000
eip 08048110  eflags 00000000
eax 080531e0  ecx 00000000  edx 080bd800  ebx 080bd800
esp 08047330  ebp 08047368  esi 00000000  edi 00000000
eip 08048880  eflags 00010297
./vxlinux: fatal error: vxproc_run trap 0xe

話は変わって、vxlinux内のコードを調べてみた。コアの部分はこんな感じ。fork&exec、ptraceなどで子プロセスを監視する代わりに、vxproc_allocでプロセスの構造体を確保して、vxproc_loadelffileで実行ファイルをロードする。そしてvxproc_runを実行すれば、プロセスが動き出す。そして、何かお痛をすれば、vxproc_runから戻ってくる。その原因がシステムコール(int 0x80)であれば、システムコールのフック処理をする。後はこれの繰り返し。

	vxproc *p = vxproc_alloc();
	vxproc_loadelffile(p, loadname, &argv[1], (const char**)environ);

	vx32_siginit();
	dumpregs(p);

	// Simple execution loop.
	for (;;) {
		int rc = vxproc_run(p);
		if (rc < 0)
			fatal("vxproc_run: %s\n", strerror(errno));
		if (rc == VXTRAP_SOFT + 0x80) {
			dosyscall(p);
			continue;
		}
		dumpregs(p);
		fatal("vxproc_run trap %#x\n", rc);
	}
	return 0;	// not reached