i386 mmap(2) fixed for LTP
Marcin Cieslak
saper at SYSTEM.PL
Mon Sep 18 17:37:10 PDT 2006
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 at 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;
More information about the freebsd-emulation
mailing list