Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bus error (core dumped) when using strcpy to a mmap'ed file

Tags:

c

strcpy

I have a simple program going this:

int main(void) {
   int fd;
   const char *text = "This is a test";

   fd = open("/tmp/msyncTest", (O_CREAT | O_TRUNC | O_RDWR), (S_IRWXU | S_IRWXG | S_IRWXO) );
   if ( fd < 0 ) {
           perror("open() error");
           return fd;
   }

    /* mmap the file. */
   void *address;
   off_t my_offset = 0;
   address = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED, fd, my_offset);

   if ( address == MAP_FAILED ) {
           perror("mmap error. " );
           return -1;
   }

    /* Move some data into the file using memory map. */
    strcpy( (char *)address, text);

    /* use msync to write changes to disk. */
    if ( msync( address, 4096 , MS_SYNC ) < 0 ) {
    perror("msync failed with error:");
        return -1;
    }
    else {
    printf("%s","msync completed successfully.");
}

    close(fd);
    unlink("/tmp/msyncTest");
}

Anything wrong with my code? I have made some simple tests and it seems that the problem comes from strcpy. But according to the definition, I see no problem.

like image 262
HuangJie Avatar asked Oct 29 '15 16:10

HuangJie


1 Answers

If

fd = open("/tmp/msyncTest", (O_CREAT | O_TRUNC | O_RDWR), (S_IRWXU | S_IRWXG | S_IRWXO) );

is successful, fd will refer to a zero-length file (O_TRUNC). The call to mmap()

address = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED, fd, my_offset);

establishes a memory-mapping, but the pages do not correspond to an object.

http://pubs.opengroup.org/onlinepubs/7908799/xsh/mmap.html has the following to say about this situation:

The system always zero-fills any partial page at the end of an object. Further, the system never writes out any modified portions of the last page of an object that are beyond its end. References within the address range starting at pa and continuing for len bytes to whole pages following the end of an object result in delivery of a SIGBUS signal.

Similarly, man mmap on Linux notes

Use of a mapped region can result in these signals:
[...]
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).

Consequently, you must ftruncate() the file to a non-zero length before mmap()ing it (unless you are mmap()ing anonymous memory).

like image 167
EOF Avatar answered Oct 26 '22 17:10

EOF