7
7

More than 5 years have passed since last update.

メモリの二重解放エラー処理調査メモ

Last updated at Posted at 2014-10-27

メモリの二重解放エラーが発生した時、
どのような処理が行われているのか調べてます。

main.c
#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しているのでしょうか。

今後も調査を続けます。

7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7