summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/linux32/linux.h9
-rw-r--r--sys/amd64/linux32/linux32_machdep.c102
2 files changed, 51 insertions, 60 deletions
diff --git a/sys/amd64/linux32/linux.h b/sys/amd64/linux32/linux.h
index ff8680ae..b7d071e 100644
--- a/sys/amd64/linux32/linux.h
+++ b/sys/amd64/linux32/linux.h
@@ -167,6 +167,15 @@ struct l_rusage {
#define LINUX_MAP_ANON 0x0020
#define LINUX_MAP_GROWSDOWN 0x0100
+struct l_mmap_argv {
+ l_uintptr_t addr;
+ l_size_t len;
+ l_int prot;
+ l_int flags;
+ l_int fd;
+ l_off_t pgoff;
+} __packed;
+
/*
* stat family of syscalls
*/
diff --git a/sys/amd64/linux32/linux32_machdep.c b/sys/amd64/linux32/linux32_machdep.c
index 1f49458..53ad3d4 100644
--- a/sys/amd64/linux32/linux32_machdep.c
+++ b/sys/amd64/linux32/linux32_machdep.c
@@ -690,16 +690,6 @@ linux_clone(struct thread *td, struct linux_clone_args *args)
return (0);
}
-/* XXX move */
-struct l_mmap_argv {
- l_ulong addr;
- l_ulong len;
- l_ulong prot;
- l_ulong flags;
- l_ulong fd;
- l_ulong pgoff;
-};
-
#define STACK_SIZE (2 * 1024 * 1024)
#define GUARD_SIZE (4 * PAGE_SIZE)
@@ -789,9 +779,44 @@ linux_mmap_common(struct thread *td, struct l_mmap_argv *linux_args)
bsd_args.flags |= MAP_ANON;
else
bsd_args.flags |= MAP_NOSYNC;
- if (linux_args->flags & LINUX_MAP_GROWSDOWN) {
+ if (linux_args->flags & LINUX_MAP_GROWSDOWN)
bsd_args.flags |= MAP_STACK;
+ /*
+ * PROT_READ, PROT_WRITE, or PROT_EXEC implies PROT_READ and PROT_EXEC
+ * on Linux/i386. We do this to ensure maximum compatibility.
+ * Linux/ia64 does the same in i386 emulation mode.
+ */
+ bsd_args.prot = linux_args->prot;
+ if (bsd_args.prot & (PROT_READ | PROT_WRITE | PROT_EXEC))
+ bsd_args.prot |= PROT_READ | PROT_EXEC;
+
+ if (linux_args->fd != -1) {
+ /*
+ * Linux follows Solaris mmap(2) description:
+ * The file descriptor fildes is opened with
+ * read permission, regardless of the
+ * protection options specified.
+ */
+
+ 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);
+ }
+
+ fdrop(fp, td);
+ }
+ bsd_args.fd = linux_args->fd;
+
+ if (linux_args->flags & LINUX_MAP_GROWSDOWN) {
/*
* The linux MAP_GROWSDOWN option does not limit auto
* growth of the region. Linux mmap with this option
@@ -814,11 +839,7 @@ linux_mmap_common(struct thread *td, struct l_mmap_argv *linux_args)
* fixed size of (STACK_SIZE - GUARD_SIZE).
*/
- /* This gives us TOS */
- bsd_args.addr = (caddr_t)PTRIN(linux_args->addr) +
- linux_args->len;
-
- if ((caddr_t)PTRIN(bsd_args.addr) >
+ if ((caddr_t)PTRIN(linux_args->addr) + linux_args->len >
p->p_vmspace->vm_maxsaddr) {
/*
* Some linux apps will attempt to mmap
@@ -837,8 +858,7 @@ linux_mmap_common(struct thread *td, struct l_mmap_argv *linux_args)
* mmap's return value.
*/
PROC_LOCK(p);
- p->p_vmspace->vm_maxsaddr =
- (char *)LINUX32_USRSTACK -
+ p->p_vmspace->vm_maxsaddr = (char *)LINUX32_USRSTACK -
lim_cur(p, RLIMIT_STACK);
PROC_UNLOCK(p);
}
@@ -856,49 +876,12 @@ linux_mmap_common(struct thread *td, struct l_mmap_argv *linux_args)
* not using VM_STACK we map the full stack, since we
* don't have a way to autogrow it.
*/
- bsd_args.addr -= bsd_args.len;
+ bsd_args.addr = (caddr_t)PTRIN(linux_args->addr) -
+ bsd_args.len;
} else {
bsd_args.addr = (caddr_t)PTRIN(linux_args->addr);
bsd_args.len = linux_args->len;
}
-
- /*
- * 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;
- if (linux_args->flags & LINUX_MAP_ANON)
- bsd_args.fd = -1;
- 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;
@@ -1181,8 +1164,7 @@ linux_mprotect(struct thread *td, struct linux_mprotect_args *uap)
bsd_args.addr = uap->addr;
bsd_args.len = uap->len;
bsd_args.prot = uap->prot;
- /* XXX PROT_READ implies PROT_EXEC; see linux_mmap_common(). */
- if ((bsd_args.prot & PROT_READ) != 0)
- bsd_args.prot |= PROT_EXEC;
+ if (bsd_args.prot & (PROT_READ | PROT_WRITE | PROT_EXEC))
+ bsd_args.prot |= PROT_READ | PROT_EXEC;
return (mprotect(td, &bsd_args));
}
OpenPOWER on IntegriCloud