From owner-svn-src-head@FreeBSD.ORG Fri Feb 17 23:47:16 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 74A59106564A; Fri, 17 Feb 2012 23:47:16 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 623968FC0A; Fri, 17 Feb 2012 23:47:16 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q1HNlGFE001385; Fri, 17 Feb 2012 23:47:16 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q1HNlGFv001379; Fri, 17 Feb 2012 23:47:16 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <201202172347.q1HNlGFv001379@svn.freebsd.org> From: Konstantin Belousov Date: Fri, 17 Feb 2012 23:47:16 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r231885 - in head/sys: compat/linux compat/svr4 i386/ibcs2 i386/linux kern X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 17 Feb 2012 23:47:16 -0000 Author: kib Date: Fri Feb 17 23:47:16 2012 New Revision: 231885 URL: http://svn.freebsd.org/changeset/base/231885 Log: Fix misuse of the kernel map in miscellaneous image activators. Vnode-backed mappings cannot be put into the kernel map, since it is a system map. Use exec_map for transient mappings, and remove the mappings with kmem_free_wakeup() to notify the waiters on available map space. Do not map the whole executable into KVA at all to copy it out into usermode. Directly use vn_rdwr() for the case of not page aligned binary. There is one place left where the potentially unbounded amount of data is mapped into exec_map, namely, in the COFF image activator enumeration of the needed shared libraries. Reviewed by: alc MFC after: 2 weeks Modified: head/sys/compat/linux/linux_misc.c head/sys/compat/svr4/imgact_svr4.c head/sys/i386/ibcs2/imgact_coff.c head/sys/i386/linux/imgact_linux.c head/sys/kern/imgact_gzip.c Modified: head/sys/compat/linux/linux_misc.c ============================================================================== --- head/sys/compat/linux/linux_misc.c Fri Feb 17 22:40:52 2012 (r231884) +++ head/sys/compat/linux/linux_misc.c Fri Feb 17 23:47:16 2012 (r231885) @@ -229,9 +229,9 @@ linux_uselib(struct thread *td, struct l struct vattr attr; vm_offset_t vmaddr; unsigned long file_offset; - vm_offset_t buffer; unsigned long bss_size; char *library; + ssize_t aresid; int error; int locked, vfslocked; @@ -308,8 +308,8 @@ linux_uselib(struct thread *td, struct l if (error) goto cleanup; - /* Pull in executable header into kernel_map */ - error = vm_mmap(kernel_map, (vm_offset_t *)&a_out, PAGE_SIZE, + /* Pull in executable header into exec_map */ + error = vm_mmap(exec_map, (vm_offset_t *)&a_out, PAGE_SIZE, VM_PROT_READ, VM_PROT_READ, 0, OBJT_VNODE, vp, 0); if (error) goto cleanup; @@ -402,24 +402,15 @@ linux_uselib(struct thread *td, struct l if (error) goto cleanup; - /* map file into kernel_map */ - error = vm_mmap(kernel_map, &buffer, - round_page(a_out->a_text + a_out->a_data + file_offset), - VM_PROT_READ, VM_PROT_READ, 0, OBJT_VNODE, vp, - trunc_page(file_offset)); - if (error) + error = vn_rdwr(UIO_READ, vp, (void *)vmaddr, file_offset, + a_out->a_text + a_out->a_data, UIO_USERSPACE, 0, + td->td_ucred, NOCRED, &aresid, td); + if (error != 0) goto cleanup; - - /* copy from kernel VM space to user space */ - error = copyout(PTRIN(buffer + file_offset), - (void *)vmaddr, a_out->a_text + a_out->a_data); - - /* release temporary kernel space */ - vm_map_remove(kernel_map, buffer, buffer + - round_page(a_out->a_text + a_out->a_data + file_offset)); - - if (error) + if (aresid != 0) { + error = ENOEXEC; goto cleanup; + } } else { #ifdef DEBUG printf("uselib: Page aligned binary %lu\n", file_offset); @@ -463,10 +454,9 @@ cleanup: VFS_UNLOCK_GIANT(vfslocked); } - /* Release the kernel mapping. */ + /* Release the temporary mapping. */ if (a_out) - vm_map_remove(kernel_map, (vm_offset_t)a_out, - (vm_offset_t)a_out + PAGE_SIZE); + kmem_free_wakeup(exec_map, (vm_offset_t)a_out, PAGE_SIZE); return (error); } Modified: head/sys/compat/svr4/imgact_svr4.c ============================================================================== --- head/sys/compat/svr4/imgact_svr4.c Fri Feb 17 22:40:52 2012 (r231884) +++ head/sys/compat/svr4/imgact_svr4.c Fri Feb 17 23:47:16 2012 (r231885) @@ -66,8 +66,8 @@ exec_svr4_imgact(imgp) struct vmspace *vmspace; vm_offset_t vmaddr; unsigned long virtual_offset, file_offset; - vm_offset_t buffer; unsigned long bss_size; + ssize_t aresid; int error; if (((a_out->a_magic >> 16) & 0xff) != 0x64) @@ -145,21 +145,15 @@ exec_svr4_imgact(imgp) if (error) goto fail; - error = vm_mmap(kernel_map, &buffer, - round_page(a_out->a_text + a_out->a_data + file_offset), - VM_PROT_READ, VM_PROT_READ, 0, - OBJT_VNODE, imgp->vp, trunc_page(file_offset)); - if (error) - goto fail; - - error = copyout((caddr_t)(buffer + file_offset), (caddr_t)vmaddr, - a_out->a_text + a_out->a_data); - - vm_map_remove(kernel_map, buffer, - buffer + round_page(a_out->a_text + a_out->a_data + file_offset)); - - if (error) - goto fail; + error = vn_rdwr(UIO_READ, imgp->vp, (void *)vmaddr, file_offset, + a_out->a_text + a_out->a_data, UIO_USERSPACE, 0, + curthread->td_ucred, NOCRED, &aresid, curthread); + if (error != 0) + goto fail; + if (aresid != 0) { + error = ENOEXEC; + goto fail; + } /* * remove write enable on the 'text' part Modified: head/sys/i386/ibcs2/imgact_coff.c ============================================================================== --- head/sys/i386/ibcs2/imgact_coff.c Fri Feb 17 22:40:52 2012 (r231884) +++ head/sys/i386/ibcs2/imgact_coff.c Fri Feb 17 23:47:16 2012 (r231885) @@ -146,10 +146,7 @@ load_coff_section(struct vmspace *vmspac error = copyout(data_buf, (caddr_t) map_addr, copy_len); - if (vm_map_remove(exec_map, - (vm_offset_t) data_buf, - (vm_offset_t) data_buf + PAGE_SIZE)) - panic("load_coff_section vm_map_remove failed"); + kmem_free_wakeup(exec_map, (vm_offset_t)data_buf, PAGE_SIZE); return error; } @@ -280,11 +277,7 @@ coff_load_file(struct thread *td, char * error = 0; dealloc_and_fail: - if (vm_map_remove(exec_map, - (vm_offset_t) ptr, - (vm_offset_t) ptr + PAGE_SIZE)) - panic("%s vm_map_remove failed", __func__); - + kmem_free_wakeup(exec_map, (vm_offset_t)ptr, PAGE_SIZE); fail: VOP_UNLOCK(vp, 0); unlocked_fail: @@ -421,10 +414,7 @@ exec_coff_imgact(imgp) } free(libbuf, M_TEMP); } - if (vm_map_remove(exec_map, - (vm_offset_t) buf, - (vm_offset_t) buf + len)) - panic("exec_coff_imgact vm_map_remove failed"); + kmem_free_wakeup(exec_map, (vm_offset_t)buf, len); if (error) goto fail; } Modified: head/sys/i386/linux/imgact_linux.c ============================================================================== --- head/sys/i386/linux/imgact_linux.c Fri Feb 17 22:40:52 2012 (r231884) +++ head/sys/i386/linux/imgact_linux.c Fri Feb 17 23:47:16 2012 (r231885) @@ -64,8 +64,8 @@ exec_linux_imgact(struct image_params *i struct vmspace *vmspace; vm_offset_t vmaddr; unsigned long virtual_offset, file_offset; - vm_offset_t buffer; unsigned long bss_size; + ssize_t aresid; int error; if (((a_out->a_magic >> 16) & 0xff) != 0x64) @@ -144,21 +144,15 @@ exec_linux_imgact(struct image_params *i if (error) goto fail; - error = vm_mmap(kernel_map, &buffer, - round_page(a_out->a_text + a_out->a_data + file_offset), - VM_PROT_READ, VM_PROT_READ, 0, OBJT_VNODE, - imgp->vp, trunc_page(file_offset)); - if (error) - goto fail; - - error = copyout((void *)(uintptr_t)(buffer + file_offset), - (void *)vmaddr, a_out->a_text + a_out->a_data); - - vm_map_remove(kernel_map, buffer, - buffer + round_page(a_out->a_text + a_out->a_data + file_offset)); - - if (error) - goto fail; + error = vn_rdwr(UIO_READ, imgp->vp, (void *)vmaddr, file_offset, + a_out->a_text + a_out->a_data, UIO_USERSPACE, 0, + curthread->td_ucred, NOCRED, &aresid, curthread); + if (error != 0) + goto fail; + if (aresid != 0) { + error = ENOEXEC; + goto fail; + } /* * remove write enable on the 'text' part Modified: head/sys/kern/imgact_gzip.c ============================================================================== --- head/sys/kern/imgact_gzip.c Fri Feb 17 22:40:52 2012 (r231884) +++ head/sys/kern/imgact_gzip.c Fri Feb 17 23:47:16 2012 (r231885) @@ -70,7 +70,7 @@ static int exec_gzip_imgact(imgp) struct image_params *imgp; { - int error, error2 = 0; + int error; const u_char *p = (const u_char *) imgp->image_header; struct imgact_gzip igz; struct inflate infl; @@ -136,22 +136,17 @@ exec_gzip_imgact(imgp) VM_PROT_READ|VM_PROT_EXECUTE,0); } - if (igz.inbuf) { - error2 = - vm_map_remove(kernel_map, (vm_offset_t) igz.inbuf, - (vm_offset_t) igz.inbuf + PAGE_SIZE); - } - if (igz.error || error || error2) { + if (igz.inbuf) + kmem_free_wakeup(exec_map, (vm_offset_t)igz.inbuf, PAGE_SIZE); + if (igz.error || error) { printf("Output=%lu ", igz.output); - printf("Inflate_error=%d igz.error=%d error2=%d where=%d\n", - error, igz.error, error2, igz.where); + printf("Inflate_error=%d igz.error=%d where=%d\n", + error, igz.error, igz.where); } if (igz.error) return igz.error; if (error) return ENOEXEC; - if (error2) - return error2; return 0; } @@ -314,18 +309,11 @@ NextByte(void *vp) if (igz->inbuf && igz->idx < (igz->offset + PAGE_SIZE)) { return igz->inbuf[(igz->idx++) - igz->offset]; } - if (igz->inbuf) { - error = vm_map_remove(kernel_map, (vm_offset_t) igz->inbuf, - (vm_offset_t) igz->inbuf + PAGE_SIZE); - if (error) { - igz->where = __LINE__; - igz->error = error; - return GZ_EOF; - } - } + if (igz->inbuf) + kmem_free_wakeup(exec_map, (vm_offset_t)igz->inbuf, PAGE_SIZE); igz->offset = igz->idx & ~PAGE_MASK; - error = vm_mmap(kernel_map, /* map */ + error = vm_mmap(exec_map, /* map */ (vm_offset_t *) & igz->inbuf, /* address */ PAGE_SIZE, /* size */ VM_PROT_READ, /* protection */