Subject: port-i386/3927: mmap doens't behave rigth in linux emulation
To: None <gnats-bugs@gnats.netbsd.org>
From: Manuel Bouyer <bouyer@antioche.lip6.fr>
List: netbsd-bugs
Date: 07/30/1997 11:04:37
>Number: 3927
>Category: port-i386
>Synopsis: mmap doens't behave rigth in linux emulation
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: gnats-admin (GNATS administrator)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Wed Jul 30 02:20:02 1997
>Last-Modified:
>Originator: Manuel Bouyer
>Organization:
LIP6, Universite Paris VI.
>Release: NetBSD-current as of a few days ago
>Environment:
NetBSD antioche.lip6.fr 1.2G NetBSD 1.2G (ANTIOCHE) #0: Wed Jul 23 13:16:32 MEST 1997 bouyer@chassiron.ensta.fr:/usr/src/sources/src_current/sys/arch/i386/compile/ANTIOCHE i386
>Description:
Some linux programs (e.g. mkdep from the kernel sources) actually uses
mmap to read a text file. They mmap an area of size (file_size + a little),
and uses the fact that the vm system fills the extra space with NULL's
to detect the end of the file. Under NetBSD, the wm subsystem seems to
use the size of the file to compute the number of pages needed, and not
the argument passed to mmap. This implies that, on a file with a size
just multiple of a page size, mmap will not map the last page (which
would be filled in with NULLs only), and thus the program will get a
SIGSEV at the end of the file.
>How-To-Repeat:
The following code will trigger the problem: compile it on a linux machine,
and uses it with 2 files: one of exactly 4k, and one of random size :
-rw-r--r-- 1 bouyer wheel 4096 Jul 30 10:31 /tmp/titi
-rwxr-xr-x 1 root wheel 1333771 Jul 24 17:24 /netbsd*
antifer:/promethee/bouyer>./badprog /netbsd
6512484
0
antifer:/promethee/bouyer>./badprog /tmp/titi
-350051
Segmentation fault (core dumped)
On a linux machine you get:
mooney:/promethee/bouyer>./badprog titi
-350051
0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/fcntl.h>
#include <sys/mman.h>
int main(int argc, char **argv)
{
char *map;
int mapsize;
int pagesizem1 = getpagesize()-1;
int fd = open(argv[1], O_RDONLY);
struct stat st;
int len;
char * hpath;
if (fd < 0) {
perror("open");
return;
}
fstat(fd, &st);
if (st.st_size == 0) {
fprintf(stderr,"%s is empty\n",argv[1]);
return;
}
mapsize = st.st_size + sizeof(unsigned int) * 2;
mapsize = (mapsize+pagesizem1) & ~pagesizem1;
map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
if (-1 == (long)map) {
perror("mkdep: mmap");
close(fd);
return;
}
close(fd);
printf("%d\n", *(int *)(map + st.st_size - sizeof(int)));
printf("%d\n", *(int *)(map + st.st_size));
munmap(map, mapsize);
}
>Fix:
Unknown (to me). I guess this is rather trivial to fix for someone
who used to hack the VM system.
I don't know how mmap should behave in this environement.
SunoS and Solaris mmap behave like NetBSD's one. But in any case, the
linux emulation is currently brocken.
>Audit-Trail:
>Unformatted: