mmap然后munmap,有时可以访问未映射的区域

时间:2014-12-25 03:10:14

标签: linux mmap

我在vmware 11.0和linux-2.6.34上遇到了这个问题,gcc 4.9.2,没有在真实硬件上测试过。 代码运行成功后,打印的消息没有SIGSEGV。但如果我在munmap之前取消注释printf,就会发现一个SIGSEGV。

在munmap()之前和之后的地图打印在以下消息中。

static void check_mmap(void){
    int fd, i;
    char *p = NULL;

    if ((fd = shm_open("xxxxxxxxxxxx", O_RDWR|O_CREAT|O_TRUNC, 0666)) == -1) {
        printf("open shm file failed.\n");
        return;
    }

    if (ftruncate(fd, 4096) == -1)
        goto out;

    p = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
    if (MAP_FAILED == p)
    goto out;

    //printf("Mapped at %p\n", p);
    getchar(); // <----- chance to print maps befor munmap

    if (munmap(p, 4096) != 0)
        printf("munmap error: %s\n", strerror(errno));

    printf("Corrupting mmap memory.\n");
    for(i = 0; i < 4095; i ++)
        p[i] = 0;
    printf("Done\n");

    getchar(); // <----- chance to print maps after munmap

out:
    close(fd);
    if (p)
        munmap(p, 4096);
}

在munmap之前映射,shm xxxxxxxxxxxx在7f3f2683a000-7f3f2683b000进行映射

00400000-00401000 r-xp 00000000 00:14 121 / mnt / hgfs / vm_shared / asan / asan1

00600000-00601000 rw-p 00000000 00:14 121 / mnt / hgfs / vm_shared / asan / asan1

7f3f25ea6000-7f3f25ebd000 r-xp 00000000 08:02 347266 /lib64/libpthread-2.11.3.so

7f3f25ebd000-7f3f260bc000 --- p 00017000 08:02 347266 /lib64/libpthread-2.11.3.so

7f3f260bc000-7f3f260bd000 r - p 00016000 08:02 347266 /lib64/libpthread-2.11.3.so

7f3f260bd000-7f3f260be000 rw-p 00017000 08:02 347266 /lib64/libpthread-2.11.3.so

7f3f260be000-7f3f260c2000 rw-p 00000000 00:00 0

7f3f260c2000-7f3f2620e000 r-xp 00000000 08:02 298091 /lib64/libc-2.11.1.so

7f3f2620e000-7f3f2640d000 --- p 0014c000 08:02 298091 /lib64/libc-2.11.1.so

7f3f2640d000-7f3f26411000 r - p 0014b000 08:02 298091 /lib64/libc-2.11.1.so

7f3f26411000-7f3f26412000 rw-p 0014f000 08:02 298091 /lib64/libc-2.11.1.so

7f3f26412000-7f3f26417000 rw-p 00000000 00:00 0

7f3f26417000-7f3f2641e000 r-xp 00000000 08:02 335978 /lib64/librt-2.11.1.so

7f3f2641e000-7f3f2661d000 --- p 00007000 08:02 335978 /lib64/librt-2.11.1.so

7f3f2661d000-7f3f2661e000 r - p 00006000 08:02 335978 /lib64/librt-2.11.1.so

7f3f2661e000-7f3f2661f000 rw-p 00007000 08:02 335978 /lib64/librt-2.11.1.so

7f3f2661f000-7f3f2663d000 r-xp 00000000 08:02 260202 /lib64/ld-2.11.1.so

7f3f2682b000-7f3f2682e000 rw-p 00000000 00:00 0

7f3f26839000-7f3f2683a000 rw-p 00000000 00:00 0

7f3f2683a000-7f3f2683b000 rw-p 00000000 00:11 16078 / dev / shm / xxxxxxxxxxxx

7f3f2683b000-7f3f2683c000 rw-p 00000000 00:00 0

7f3f2683c000-7f3f2683d000 r - p 0001d000 08:02 260202 /lib64/ld-2.11.1.so

7f3f2683d000-7f3f2683e000 rw-p 0001e000 08:02 260202 /lib64/ld-2.11.1.so

7f3f2683e000-7f3f2683f000 rw-p 00000000 00:00 0

7fffd9ce3000-7fffd9d04000 rw-p 00000000 00:00 0 [stack]

7fffd9dff000-7fffd9e00000 r-xp 00000000 00:00 0 [vdso]

ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]


在munmap之后映射,shm已成功取消映射。

00400000-00401000 r-xp 00000000 00:14 121 / mnt / hgfs / vm_shared / asan / asan1

00600000-00601000 rw-p 00000000 00:14 121 / mnt / hgfs / vm_shared / asan / asan1

7f3f25ea6000-7f3f25ebd000 r-xp 00000000 08:02 347266 /lib64/libpthread-2.11.3.so

7f3f25ebd000-7f3f260bc000 --- p 00017000 08:02 347266 /lib64/libpthread-2.11.3.so

7f3f260bc000-7f3f260bd000 r - p 00016000 08:02 347266 /lib64/libpthread-2.11.3.so

7f3f260bd000-7f3f260be000 rw-p 00017000 08:02 347266 /lib64/libpthread-2.11.3.so

7f3f260be000-7f3f260c2000 rw-p 00000000 00:00 0

7f3f260c2000-7f3f2620e000 r-xp 00000000 08:02 298091 /lib64/libc-2.11.1.so

7f3f2620e000-7f3f2640d000 --- p 0014c000 08:02 298091 /lib64/libc-2.11.1.so

7f3f2640d000-7f3f26411000 r - p 0014b000 08:02 298091 /lib64/libc-2.11.1.so

7f3f26411000-7f3f26412000 rw-p 0014f000 08:02 298091 /lib64/libc-2.11.1.so

7f3f26412000-7f3f26417000 rw-p 00000000 00:00 0

7f3f26417000-7f3f2641e000 r-xp 00000000 08:02 335978 /lib64/librt-2.11.1.so

7f3f2641e000-7f3f2661d000 --- p 00007000 08:02 335978 /lib64/librt-2.11.1.so

7f3f2661d000-7f3f2661e000 r - p 00006000 08:02 335978 /lib64/librt-2.11.1.so

7f3f2661e000-7f3f2661f000 rw-p 00007000 08:02 335978 /lib64/librt-2.11.1.so

7f3f2661f000-7f3f2663d000 r-xp 00000000 08:02 260202 /lib64/ld-2.11.1.so

7f3f2682b000-7f3f2682e000 rw-p 00000000 00:00 0

7f3f26839000-7f3f2683b000 rw-p 00000000 00:00 0

7f3f2683b000-7f3f2683c000 rw-p 00000000 00:00 0

7f3f2683c000-7f3f2683d000 r - p 0001d000 08:02 260202 /lib64/ld-2.11.1.so

7f3f2683d000-7f3f2683e000 rw-p 0001e000 08:02 260202 /lib64/ld-2.11.1.so

7f3f2683e000-7f3f2683f000 rw-p 00000000 00:00 0

7fffd9ce3000-7fffd9d04000 rw-p 00000000 00:00 0 [stack]

7fffd9dff000-7fffd9e00000 r-xp 00000000 00:00 0 [vdso]

ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]


以下是objdump

0000000000400890 <main>:
400890:       55                      push   %rbp
400891:       53                      push   %rbx
400892:       ba b6 01 00 00          mov    $0x1b6,%edx
400897:       be 42 02 00 00          mov    $0x242,%esi
40089c:       bf 9c 0a 40 00          mov    $0x400a9c,%edi
4008a1:       48 83 ec 08             sub    $0x8,%rsp
4008a5:       e8 fe fd ff ff          callq  4006a8 <shm_open@plt>
4008aa:       83 f8 ff                cmp    $0xffffffffffffffff,%eax
4008ad:       89 c3                   mov    %eax,%ebx
4008af:       0f 84 c0 00 00 00       je     400975 <main+0xe5>
4008b5:       be 00 10 00 00          mov    $0x1000,%esi
4008ba:       89 c7                   mov    %eax,%edi
4008bc:       e8 37 fe ff ff          callq  4006f8 <ftruncate@plt>
4008c1:       83 f8 ff                cmp    $0xffffffffffffffff,%eax
4008c4:       0f 84 9b 00 00 00       je     400965 <main+0xd5>
4008ca:       45 31 c9                xor    %r9d,%r9d
4008cd:       31 ff                   xor    %edi,%edi
4008cf:       41 89 d8                mov    %ebx,%r8d
4008d2:       b9 02 00 00 00          mov    $0x2,%ecx
4008d7:       ba 03 00 00 00          mov    $0x3,%edx
4008dc:       be 00 10 00 00          mov    $0x1000,%esi
4008e1:       e8 22 fe ff ff          callq  400708 <mmap@plt>
4008e6:       48 83 f8 ff             cmp    $0xffffffffffffffff,%rax
4008ea:       48 89 c5                mov    %rax,%rbp
4008ed:       0f 84 8e 00 00 00       je     400981 <main+0xf1>
4008f3:       48 8b 3d 0e 05 20 00    mov    0x20050e(%rip),%rdi        # 600e08   <__TMC_END__>
4008fa:       e8 b9 fd ff ff          callq  4006b8 <_IO_getc@plt>
4008ff:       be 00 10 00 00          mov    $0x1000,%esi
400904:       48 89 ef                mov    %rbp,%rdi
400907:       e8 dc fd ff ff          callq  4006e8 <munmap@plt>
40090c:       85 c0                   test   %eax,%eax
40090e:       75 7a                   jne    40098a <main+0xfa>
400910:       bf d1 0a 40 00          mov    $0x400ad1,%edi
400915:       e8 6e fd ff ff          callq  400688 <puts@plt>
40091a:       48 8d 8d ff 0f 00 00    lea    0xfff(%rbp),%rcx
400921:       48 89 ea                mov    %rbp,%rdx
400924:       0f 1f 40 00             nopl   0x0(%rax)
400928:       c6 02 00                movb   $0x0,(%rdx)
40092b:       48 83 c2 01             add    $0x1,%rdx
40092f:       48 39 ca                cmp    %rcx,%rdx
400932:       75 f4                   jne    400928 <main+0x98>
400934:       bf e9 0a 40 00          mov    $0x400ae9,%edi
400939:       e8 4a fd ff ff          callq  400688 <puts@plt>
40093e:       48 8b 3d c3 04 20 00    mov    0x2004c3(%rip),%rdi        # 600e08 <__TMC_END__>
400945:       e8 6e fd ff ff          callq  4006b8 <_IO_getc@plt>

2 个答案:

答案 0 :(得分:0)

您正在调用“未定义的行为”。什么事情都可能发生。你不能抱怨说,在一种情况下,你比其他情况更喜欢结果,而两者都有未定义的行为。只是停止运行无效代码。

答案 1 :(得分:0)

  

以下代码成功运行并且没有打印消息   SIGSEGV。但是如果我在munmap之前取消注释printf,那么SIGSEGV就是   捕获。

这种表面上令人吃惊的行为有一个简单的解释。访问未映射的Linux内存时,确实需要 Segmentation fault 。只是在没有munmap 之前的 printf的情况下,printf("Corrupting mmap memory.\n")之后的munmap()构成了程序首次使用stdout,并且在第一次使用时,{/ 1}},Linux / GNU C库通过mmap()分配流缓冲区,从而完全重新映射之前未映射的内存页,因此p[i]可以无故障地访问新的映射内存。