diff options
author | jkim <jkim@FreeBSD.org> | 2007-02-15 00:54:40 +0000 |
---|---|---|
committer | jkim <jkim@FreeBSD.org> | 2007-02-15 00:54:40 +0000 |
commit | df99d574b5108aba65b940cbb910d8f6dae0b05f (patch) | |
tree | 7ac3a3ba87c37bfd781cdcc61e412702c7f93cc9 /sys/i386/linux/linux_machdep.c | |
parent | 494959a002ebd44883ca0f80a6ab843faa66893b (diff) | |
download | FreeBSD-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.c | 112 |
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; |