Linux カーネル 0 day exploit 祭り †Linux カーネルの zero-day exploit コード、リリースされる (slashdot Japan) 要するに,注意が足りないコードに gcc の最適化が重なって生じた穴だそうである. 注意が足りない †問題のコード. static unsigned int tun_chr_poll(struct file *file, poll_table * wait) { struct tun_file *tfile = file->private_data; struct tun_struct *tun = __tun_get(tfile); + struct sock *sk = tun->sk; + unsigned int mask = 0; if (!tun) return POLLERR; ポインタが NULL かどうかチェックする前にそのポインタの指し示す構造体のメンバにアクセスしてしまっている. gcc の最適化 †上記のソースであるが,
ということで,gcc の最適化で if 文全体が削られてしまうそうなのである. exploit では,ここで 0x00000000 に mmap() でメモリを割り当ててこの例外の起きる条件を変えて…ということらしい. 手元の環境では †試しに似たようなコードを書いてみた. $ cat exploit.c struct hoge { int a, b, c, d; }; int foo ( struct hoge *h ) { int x = h->b; if ( !h ) return 0; return x; } gcc のバージョンはこんな感じ. $ gcc --version gcc (Debian 4.3.3-13) 4.3.3 Copyright (C) 2008 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. コンパイルして,オブジェクトファイルをディスアセンブル. $ gcc -O0 -c exploit.c $ objdump -d exploit.o | sed 's/^/ /' exploit.o: file format elf32-i386 Disassembly of section .text: 00000000 <foo>: 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: 83 ec 14 sub $0x14,%esp 6: 8b 45 08 mov 0x8(%ebp),%eax 9: 8b 40 04 mov 0x4(%eax),%eax c: 89 45 fc mov %eax,-0x4(%ebp) f: 83 7d 08 00 cmpl $0x0,0x8(%ebp) 13: 75 09 jne 1e <foo+0x1e> 15: c7 45 ec 00 00 00 00 movl $0x0,-0x14(%ebp) 1c: eb 06 jmp 24 <foo+0x24> 1e: 8b 45 fc mov -0x4(%ebp),%eax 21: 89 45 ec mov %eax,-0x14(%ebp) 24: 8b 45 ec mov -0x14(%ebp),%eax 27: c9 leave 28: c3 ret if 文相当の 0 との比較は残っている. 最適化オプションを付けてコンパイル,ディスアセンブル. $ gcc -O2 -c exploit.c $ objdump -d exploit.o exploit.o: file format elf32-i386 Disassembly of section .text: 00000000 <foo>: 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: 8b 45 08 mov 0x8(%ebp),%eax 6: 5d pop %ebp 7: 8b 40 04 mov 0x4(%eax),%eax a: c3 ret if 文部分がざっくり消えてしまっている. ARM では †ARM のクロスコンパイラで試してみた. $ arm-linux-gnueabi-gcc --version arm-linux-gnueabi-gcc (GCC) 4.2.4 (Debian 4.2.4-6) Copyright (C) 2007 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 最適化オプション付きでコンパイル,ディスアセンブル. $ arm-linux-gnueabi-gcc -O2 -c exploit.c $ arm-linux-gnueabi-objdump -d exploit.o | sed 's/^/ /' exploit.o: file format elf32-littlearm Disassembly of section .text: 00000000 <foo>: 0: e5900004 ldr r0, [r0, #4] 4: e12fff1e bx lr これも if 文がざっくり削られてますね. x86 以外でも気をつけたほうがいいかもしれません. 祭りの続き †MIPS でもやってみた. やっぱり同様の最適化処理はされるようだ. $ mipsel-linux-gnu-gcc --version mipsel-linux-gnu-gcc (Debian 4.4.0-10) 4.4.0 Copyright (C) 2009 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ mipsel-linux-gnu-gcc -O2 -c exploit.c $ mipsel-linux-gnu-objdump -d exploit.o exploit.o: file format elf32-tradlittlemips Disassembly of section .text: 00000000 <foo>: 0: 8c820004 lw v0,4(a0) 4: 03e00008 jr ra 8: 00000000 nop c: 00000000 nop |