diff options
author | kib <kib@FreeBSD.org> | 2012-02-17 23:47:16 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2012-02-17 23:47:16 +0000 |
commit | abd1094f175810ed5ec686a897d27fae63d1ca87 (patch) | |
tree | 8d01d9dbb96b87e94aed60c4fc7d2b35c530a0c8 /sys/compat | |
parent | b7cff9346353517bc204fe45512c010fcab10186 (diff) | |
download | FreeBSD-src-abd1094f175810ed5ec686a897d27fae63d1ca87.zip FreeBSD-src-abd1094f175810ed5ec686a897d27fae63d1ca87.tar.gz |
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
Diffstat (limited to 'sys/compat')
-rw-r--r-- | sys/compat/linux/linux_misc.c | 34 | ||||
-rw-r--r-- | sys/compat/svr4/imgact_svr4.c | 26 |
2 files changed, 22 insertions, 38 deletions
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index dacfb69..d8ce2a8 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -229,9 +229,9 @@ linux_uselib(struct thread *td, struct linux_uselib_args *args) 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 linux_uselib_args *args) 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 linux_uselib_args *args) 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); } diff --git a/sys/compat/svr4/imgact_svr4.c b/sys/compat/svr4/imgact_svr4.c index 9b19ec3..69e8890 100644 --- a/sys/compat/svr4/imgact_svr4.c +++ b/sys/compat/svr4/imgact_svr4.c @@ -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 |