Date: Sun, 31 Jul 2005 17:18:01 +0300 From: Giorgos Keramidas <keramida@freebsd.org> To: freebsd-current@freebsd.org Subject: mmap bug? Message-ID: <20050731141801.GA49300@gothmog.gr>
next in thread | raw e-mail | index | archive | help
The following program can be used to mmap() a region outside of the current size of a file and then write to it. Should this ``expand'' the current file size? If not, should writes on this area fail? What's more interesting is that after running it on -CURRENT, I can write data that is "attached" to the file but this doesn't affect the current size of the file. The test program I used was: # #include <sys/mman.h> # #include <sys/stat.h> # # #include <err.h> # #include <errno.h> # #include <fcntl.h> # #include <stdio.h> # #include <stdlib.h> # #include <unistd.h> # # static int mmap_test(char *fname, size_t offset, size_t len); # static int mmap_dump(unsigned char *, size_t); # static int mmap_write_test(unsigned char *, size_t); # static void usage(void); # # int # main(int argc, char *argv[]) # { # char *fname, *errp; # long val; # size_t offset, len; # # if (argc != 4) # usage(); # # fname = argv[1]; # # errno = 0; # errp = NULL; # val = strtol(argv[2], &errp, 0); # if ((errp != NULL && *errp != '\0') || errno != 0) # err(1, "strtol: %s", argv[2]); # offset = (size_t)val; # # errno = 0; # errp = NULL; # val = strtol(argv[3], &errp, 0); # if ((errp != NULL && *errp != '\0') || errno != 0) # err(1, "strtol: %s", argv[3]); # len = (size_t)val; # # if (mmap_test(fname, offset, len) != 0) # exit(EXIT_FAILURE); # # return (0); # } # # static void # usage() # { # fprintf(stderr, "usage: foo file offset len\n"); # exit(EXIT_FAILURE); # } # # static int # mmap_test(char *fname, size_t offset, size_t len) # { # int fd; # void *ptr; # # fd = open(fname, O_CREAT | O_RDWR, S_IREAD | S_IWRITE); # if (fd == -1) # err(1, "open: %s", fname); # # ptr = mmap(NULL, len, PROT_READ | PROT_WRITE, # MAP_SHARED, fd, offset); # if (ptr == NULL) # err(1, "mmap"); # # mmap_dump((unsigned char *)ptr, len); # mmap_write_test((unsigned char *)ptr, len); # mmap_dump((unsigned char *)ptr, len); # # if (munmap(ptr, len) != 0) # err(1, "munmap"); # # close(fd); # return (0); # } # # static int # mmap_dump(unsigned char *p, size_t len) # { # size_t k; # # for (k = 0; k < len; k++) { # if ((k % 16) == 0) # printf("%08lx: ", (unsigned long)k); # printf(" %02x", p[k]); # if ((k % 16) == 15) # printf("\n"); # } # if ((k % 16) != 15) # printf("\n"); # return (0); # } # # static int # mmap_write_test(unsigned char *p, size_t len) # { # size_t k; # # for (k = 0; k < len; k++) # p[k] = (unsigned char)(k % 256); # return (0); # } Here's a sample run: # gothmog:/tmp/foo$ dd if=/dev/zero of=tempfile bs=512 count=10 # 10+0 records in # 10+0 records out # 5120 bytes transferred in 0.000575 secs (8903332 bytes/sec) # gothmog:/tmp/foo$ ls -l tempfile # -rw-rw-r-- 1 giorgos wheel - 5120 Jul 31 17:12 tempfile ok, the file has been created with the right size. # gothmog:/tmp/foo$ ./foo tempfile 5120 60 # 00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 # 00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 # 00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 # 00000030: 00 00 00 00 00 00 00 00 00 00 00 00 # 00000000: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f # 00000010: 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f # 00000020: 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f # 00000030: 30 31 32 33 34 35 36 37 38 39 3a 3b mmap() succeeded and wrote after the previous end of the file. # gothmog:/tmp/foo$ ls -l tempfile # -rw-rw-r-- 1 giorgos wheel - 5120 Jul 31 17:12 tempfile # gothmog:/tmp/foo$ hd tempfile # 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| # * # 00001400 The size of the file is still the same! # gothmog:/tmp/foo$ ./foo tempfile 5120 60 # 00000000: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f # 00000010: 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f # 00000020: 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f # 00000030: 30 31 32 33 34 35 36 37 38 39 3a 3b # 00000000: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f # 00000010: 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f # 00000020: 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f # 00000030: 30 31 32 33 34 35 36 37 38 39 3a 3b Somehow, the data written by the first mmap() is still there, but is not visible as part of the file size or by using ``normal'' commands that access its contents.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20050731141801.GA49300>