summaryrefslogtreecommitdiffstats
path: root/sys/i386/linux/linux_machdep.c
diff options
context:
space:
mode:
authorjkim <jkim@FreeBSD.org>2007-02-15 00:54:40 +0000
committerjkim <jkim@FreeBSD.org>2007-02-15 00:54:40 +0000
commitdf99d574b5108aba65b940cbb910d8f6dae0b05f (patch)
tree7ac3a3ba87c37bfd781cdcc61e412702c7f93cc9 /sys/i386/linux/linux_machdep.c
parent494959a002ebd44883ca0f80a6ab843faa66893b (diff)
downloadFreeBSD-src-df99d574b5108aba65b940cbb910d8f6dae0b05f.zip
FreeBSD-src-df99d574b5108aba65b940cbb910d8f6dae0b05f.tar.gz
MFP4: 113025, 113146, 113177, 113203, 113500, 113546, 113570
- PROT_READ, PROT_WRITE, or PROT_EXEC implies PROT_READ and PROT_EXEC. Linux/ia64's i386 emulation layer does this and it complies with Linux header files. This fixes mmap05 LTP test case on amd64. - Do not adjust stack size when failure has occurred. - Synchronize i386 mmap/mprotect with amd64.
Diffstat (limited to 'sys/i386/linux/linux_machdep.c')
-rw-r--r--sys/i386/linux/linux_machdep.c112
1 files changed, 58 insertions, 54 deletions
diff --git a/sys/i386/linux/linux_machdep.c b/sys/i386/linux/linux_machdep.c
index d07cbd5..e909d51 100644
--- a/sys/i386/linux/linux_machdep.c
+++ b/sys/i386/linux/linux_machdep.c
@@ -584,16 +584,6 @@ linux_clone(struct thread *td, struct linux_clone_args *args)
return (0);
}
-/* XXX move */
-struct l_mmap_argv {
- l_caddr_t addr;
- l_int len;
- l_int prot;
- l_int flags;
- l_int fd;
- l_int pos;
-};
-
#define STACK_SIZE (2 * 1024 * 1024)
#define GUARD_SIZE (4 * PAGE_SIZE)
@@ -611,12 +601,12 @@ linux_mmap2(struct thread *td, struct linux_mmap2_args *args)
args->flags, args->fd, args->pgoff);
#endif
- linux_args.addr = (l_caddr_t)args->addr;
+ linux_args.addr = args->addr;
linux_args.len = args->len;
linux_args.prot = args->prot;
linux_args.flags = args->flags;
linux_args.fd = args->fd;
- linux_args.pos = args->pgoff * PAGE_SIZE;
+ linux_args.pgoff = args->pgoff * PAGE_SIZE;
return (linux_mmap_common(td, &linux_args));
}
@@ -635,7 +625,7 @@ linux_mmap(struct thread *td, struct linux_mmap_args *args)
if (ldebug(mmap))
printf(ARGS(mmap, "%p, %d, %d, 0x%08x, %d, %d"),
(void *)linux_args.addr, linux_args.len, linux_args.prot,
- linux_args.flags, linux_args.fd, linux_args.pos);
+ linux_args.flags, linux_args.fd, linux_args.pgoff);
#endif
return (linux_mmap_common(td, &linux_args));
@@ -679,9 +669,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
@@ -704,10 +729,8 @@ 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 = linux_args->addr + linux_args->len;
-
- if (bsd_args.addr > p->p_vmspace->vm_maxsaddr) {
+ if ((caddr_t)PTRIN(linux_args->addr) + linux_args->len >
+ p->p_vmspace->vm_maxsaddr) {
/*
* Some linux apps will attempt to mmap
* thread stacks near the top of their
@@ -743,45 +766,13 @@ 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 = linux_args->addr;
+ bsd_args.addr = (caddr_t)PTRIN(linux_args->addr);
bsd_args.len = linux_args->len;
}
-
- bsd_args.prot = linux_args->prot;
- 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 = linux_args->pos;
+ bsd_args.pos = linux_args->pgoff;
bsd_args.pad = 0;
#ifdef DEBUG
@@ -801,6 +792,19 @@ linux_mmap_common(struct thread *td, struct l_mmap_argv *linux_args)
}
int
+linux_mprotect(struct thread *td, struct linux_mprotect_args *uap)
+{
+ struct mprotect_args bsd_args;
+
+ bsd_args.addr = uap->addr;
+ bsd_args.len = uap->len;
+ bsd_args.prot = uap->prot;
+ if (bsd_args.prot & (PROT_READ | PROT_WRITE | PROT_EXEC))
+ bsd_args.prot |= PROT_READ | PROT_EXEC;
+ return (mprotect(td, &bsd_args));
+}
+
+int
linux_pipe(struct thread *td, struct linux_pipe_args *args)
{
int error;
OpenPOWER on IntegriCloud