メモリの二重解放エラーが発生した時、
どのような処理が行われているのか調べてます。
# include <stdio.h>
main(void)
{
FILE *fp = fopen("hogehoge", "w");
fclose(fp);
fclose(fp);
}
コンパイルして実行すると
*** Error in ``./a.out': double free or corruption (top): 0x08dbd008 *** zsh: abort (core dumped) ./a.out
とメモリの二重解放を教えてくれるメッセージが。
(通常ならglibcがバックトレースやメモリマップを出力してくれるそうですが、
私の環境では何故か出力されませんでした)
・straceしてみる
% strace ./a.out
==================ここから実行結果======================
execve("./a.out", ["./a.out"], [/* 73 vars /]) = 0
brk(0) = 0x9662000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7740000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=80341, ...}) = 0
mmap2(NULL, 80341, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb772c000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\340\233\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1758972, ...}) = 0
mmap2(NULL, 1768060, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb757c000
mprotect(0xb7725000, 4096, PROT_NONE) = 0
mmap2(0xb7726000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1a9000) = 0xb7726000
mmap2(0xb7729000, 10876, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7729000
close(3) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb757b000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb757b940, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0xb7726000, 8192, PROT_READ) = 0
mprotect(0x8049000, 4096, PROT_READ) = 0
mprotect(0xb7763000, 4096, PROT_READ) = 0
munmap(0xb772c000, 80341)★←メモリ解放 = 0
brk(0) = 0x9662000
brk(0x9683000) = 0x9683000
open("hogehoge", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
close(3) = 0
open("/dev/tty", O_RDWR|O_NOCTTY|O_NONBLOCK) = 3
writev(3, [{"** Error in `", 14}, {"./a.out", 7}, {"': ", 3}, {"double free or corruption (top)", 31}, {": 0x", 4}, {"09662008", 8}, {" \n", 5}], 7 Error in `./a.out': double free or corruption (top): 0x09662008 ***
) = 72
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb773f000★←ここでエラー発生?
rt_sigprocmask(SIG_UNBLOCK, [ABRT], NULL, 8) = 0
gettid() = 9536
tgkill(9536, 9536, SIGABRT) = 0
--- SIGABRT {si_signo=SIGABRT, si_code=SI_TKILL, si_pid=9536, si_uid=1000} ---
+++ killed by SIGABRT (core dumped) +++
zsh: abort (core dumped) strace ./a.out
==================ここまで実行結果======================
munmap()でメモリを解放しているようですが、
解放したアドレス0xb772c000が
その後アクセスされてるようには見えませんね。
システムコールでメモリに不正なアクセスが行われる前に、
何かがそれ検知してプロセスをkillしているのでしょうか。
今後も調査を続けます。