Date: Tue, 19 Sep 2006 02:36:51 +0200 From: Marcin Cieslak <saper@SYSTEM.PL> To: emulation@freebsd.org Subject: i386 mmap(2) fixed for LTP Message-ID: <450F3BA3.40304@SYSTEM.PL>
next in thread | raw e-mail | index | archive | help
Hallo, Using my mmap fingerprinter (see amd64 post above) I have managed to compare basic mmap(2) behaviour between real Linux and FreeBSD machine. Our mmap(2) allows you map write-only file for writing, Linux is giving up immediately on that. (Probably because they always need the file to be open for reading as well and then they add PROT_READ internally). Using this patch I guess we have all mmap()-related LTP issues solved. This fixes outstanding map07 test. I guess that writev03 and writev04 - that started to fail after my initial quick fix for mmap() - were just false positives initially. Since linuxolator mmap() added PROT_READ that gave access to whole iovec address space, writev() calls suceeded although not in a way meant by author tests: http://sf.net/tracker/index.php?func=detail&aid=1561083&group_id=3382&atid=103382 The only thing left is the amd64 part of the fix for mmap(2). Please feel free to review. -- << Marcin Cieslak // saper@system.pl >> Index: /usr/src/sys/i386/linux/linux_machdep.c =================================================================== RCS file: /usr/home/ncvs/src/sys/i386/linux/linux_machdep.c,v retrieving revision 1.48.2.1 diff -u -u -r1.48.2.1 linux_machdep.c --- /usr/src/sys/i386/linux/linux_machdep.c 4 Aug 2005 23:25:32 -0000 1.48.2.1 +++ /usr/src/sys/i386/linux/linux_machdep.c 19 Sep 2006 00:34:53 -0000 @@ -31,6 +31,8 @@ #include <sys/param.h> #include <sys/systm.h> +#include <sys/file.h> +#include <sys/fcntl.h> #include <sys/imgact.h> #include <sys/lock.h> #include <sys/malloc.h> @@ -469,9 +471,19 @@ off_t pos; } */ bsd_args; int error; + struct file *fp; error = 0; bsd_args.flags = 0; + fp = NULL; + + /* Linux mmap(2): + * You must specify exactly one of MAP_SHARED and MAP_PRIVATE. + */ + if (! ((linux_args->flags & LINUX_MAP_SHARED) ^ + (linux_args->flags & LINUX_MAP_PRIVATE))) + return EINVAL; + if (linux_args->flags & LINUX_MAP_SHARED) bsd_args.flags |= MAP_SHARED; if (linux_args->flags & LINUX_MAP_PRIVATE) @@ -549,11 +561,34 @@ bsd_args.len = linux_args->len; } - bsd_args.prot = linux_args->prot | PROT_READ; /* always required */ - if (linux_args->flags & LINUX_MAP_ANON) + bsd_args.prot = linux_args->prot; + if (linux_args->flags & LINUX_MAP_ANON) { bsd_args.fd = -1; - else + } else { + /* + * Linux follows Solaris mmap(2) description: + * The file descriptor fildes is opened with + * read permission, regardless of the + * protection options specified. + * If PROT_WRITE is specified, the application + * must have opened the file descriptor + * fildes with write permission unless + * MAP_PRIVATE is specified in the flags + * argument as described below. + */ + + if ((error = fget(td, linux_args->fd, &fp)) != 0) + return error; + if (fp->f_type != DTYPE_VNODE) + return EINVAL; + + /* Linux mmap() just fails for O_WRONLY files */ + if (! (fp->f_flag & FREAD)) + return EACCES; + bsd_args.fd = linux_args->fd; + fdrop(fp, td); + } bsd_args.pos = linux_args->pos; bsd_args.pad = 0;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?450F3BA3.40304>