Sharp.Liu
Sharp.Liu

Reputation: 1

why mremap after only access 4096 byte memory?

The below code begin mmap(initlen=10), later remap(nsize=400000) and access remap memory address access 0x7ffff7f8c000 to 0x7ffff7f8cfff is ok, but in the 0x7ffff7f8d000 cause access error

#define _GNU_SOURCE
#include <stdio.h>
#include <limits.h>
#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>


int main()
{
    int i;
    char *p;
    void *base;
    const int initlen = 10;
    const int nsize = 400000;

    const char *fname = "/tmp/task.0";
    int fd = open(fname, O_CREAT|O_RDWR, 0600);
    if (fd == -1) {
        return 1;
    }

    if (ftruncate(fd, initlen) < 0) {
        return 1;
    }

    base = mmap(NULL, initlen, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    if (base == MAP_FAILED) {
        return 1;
    }

    // now remap big page.
    base = mremap(base, initlen, nsize, MREMAP_MAYMOVE);
    if (base == MAP_FAILED) {
        printf("mremap fail, %s\n", strerror(errno));
        return 1;
    }

    p = base;
    for (i = 0; i < nsize; i++) {
        printf("%p\n", p);
        *p = i % CHAR_MAX;
        ++p;
    }

    return 0;
}

mremap after gdb show the "/tmp/task.0" region is 0x7ffff7f8c000-0x7ffff7fee000, access error in the 0x7ffff7f8d000, why???

37      base = mremap(base, initlen, nsize, MREMAP_MAYMOVE);
(gdb)
38      if (base == MAP_FAILED) {
(gdb)
43      p = base;
(gdb)
44      for (i = 0; i < nsize; i++) {
(gdb) p base
$1 = (void *) 0x7ffff7f8c000
(gdb) i proc mappings
process 3333
Mapped address spaces:

          Start Addr           End Addr       Size     Offset objfile
            0x400000           0x401000     0x1000        0x0 /tmp/a.out
            0x600000           0x601000     0x1000        0x0 /tmp/a.out
            0x601000           0x602000     0x1000     0x1000 /tmp/a.out
      0x7ffff7a0e000     0x7ffff7bd1000   0x1c3000        0x0 /usr/lib64/libc-2.17.so
      0x7ffff7bd1000     0x7ffff7dd0000   0x1ff000   0x1c3000 /usr/lib64/libc-2.17.so
      0x7ffff7dd0000     0x7ffff7dd4000     0x4000   0x1c2000 /usr/lib64/libc-2.17.so
      0x7ffff7dd4000     0x7ffff7dd6000     0x2000   0x1c6000 /usr/lib64/libc-2.17.so
      0x7ffff7dd6000     0x7ffff7ddb000     0x5000        0x0
      0x7ffff7ddb000     0x7ffff7dfd000    0x22000        0x0 /usr/lib64/ld-2.17.so
      0x7ffff7f8c000     0x7ffff7fee000    0x62000        0x0 /tmp/task.0
      0x7ffff7fee000     0x7ffff7ff1000     0x3000        0x0
      0x7ffff7ff9000     0x7ffff7ffa000     0x1000        0x0
      0x7ffff7ffa000     0x7ffff7ffc000     0x2000        0x0 [vdso]
      0x7ffff7ffc000     0x7ffff7ffd000     0x1000    0x21000 /usr/lib64/ld-2.17.so
      0x7ffff7ffd000     0x7ffff7ffe000     0x1000    0x22000 /usr/lib64/ld-2.17.so
      0x7ffff7ffe000     0x7ffff7fff000     0x1000        0x0
      0x7ffffffde000     0x7ffffffff000    0x21000        0x0 [stack]
  0xffffffffff600000 0xffffffffff601000     0x1000        0x0 [vsyscall]

Program received signal SIGBUS, Bus error.
0x0000000000400831 in main () at ./test.c:46
46          *p = i % CHAR_MAX;
(gdb) p p
$2 = 0x7ffff7f8d000 <Address 0x7ffff7f8d000 out of bounds>

Upvotes: 0

Views: 240

Answers (1)

gudok
gudok

Reputation: 4179

It is not related to mremap. It is just how file mappings work. SIGBUS means that you tried to access file region past its EOF (see manual page mmap(3)).

SIGBUS Attempted access to a portion of the buffer that does not correspond to the file (for example, beyond the end of the file, including the case where another process has truncated the file).

This is different from SIGSEGV, which is sent when you try to access virtual address which doesn't exist in your process, or when protection error occurs (e.g. attempt to write in read-only address).

To answer the question why you can access first 0xfff bytes without getting SIGBUS (even though file size is only 10 bytes), this is because memory management happens in terms of 4096 byte pages. Note however that even though you can access bytes 10..4095, this region is not backed by file. Everything you write into those bytes, won't be written into file.

Upvotes: 1

Related Questions