MFi386 rev 1.56:

Bring the linux mmap code more into line with how linux (2.4.x) behaves.

Tested by:	Scot Hetzel <swhetzel@gmail.com> on amd64 without PROT_EXEC

Additionally to the i386 version always use PROT_EXEC in the mapping like the
previous version of the amd64 code did. We need to examinate this further to
decide what the right thing to do is. For now this fixes several problems in
the LTP test runs and should behave regarding PROT_EXEC like before.
This commit is contained in:
Alexander Leidinger 2007-01-06 15:58:34 +00:00
parent 8b5b885047
commit 4f383e20a9

View File

@ -34,6 +34,8 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/file.h>
#include <sys/fcntl.h>
#include <sys/clock.h>
#include <sys/imgact.h>
#include <sys/limits.h>
@ -728,9 +730,20 @@ linux_mmap_common(struct thread *td, struct l_mmap_argv *linux_args)
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)
@ -813,17 +826,44 @@ linux_mmap_common(struct thread *td, struct l_mmap_argv *linux_args)
bsd_args.addr = (caddr_t)PTRIN(linux_args->addr);
bsd_args.len = linux_args->len;
}
/*
* XXX i386 Linux always emulator forces PROT_READ on (why?)
* so we do the same. We add PROT_EXEC to work around buggy
* applications (e.g. Java) that take advantage of the fact
* that execute permissions are not enforced by x86 CPUs.
* We add PROT_EXEC to work around buggy applications (e.g. Java)
* that take advantage of the fact that execute permissions are not
* enforced by x86 CPUs.
*/
bsd_args.prot = linux_args->prot | PROT_EXEC | PROT_READ;
bsd_args.prot = linux_args->prot | PROT_EXEC;
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 flag
* argument as described below.
*/
if ((error = fget(td, linux_args->fd, &fp)) != 0)
return (error);
if (fp->f_type != DTYPE_VNODE) {
fdrop(fp, td);
return (EINVAL);
}
/* Linux mmap() just fails for O_WRONLY files */
if (! (fp->f_flag & FREAD)) {
fdrop(fp, td);
return (EACCES);
}
bsd_args.fd = linux_args->fd;
fdrop(fp, td);
}
bsd_args.pos = (off_t)linux_args->pgoff * PAGE_SIZE;
bsd_args.pad = 0;