summaryrefslogtreecommitdiffstats
path: root/sys/compat
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2012-02-17 23:47:16 +0000
committerkib <kib@FreeBSD.org>2012-02-17 23:47:16 +0000
commitabd1094f175810ed5ec686a897d27fae63d1ca87 (patch)
tree8d01d9dbb96b87e94aed60c4fc7d2b35c530a0c8 /sys/compat
parentb7cff9346353517bc204fe45512c010fcab10186 (diff)
downloadFreeBSD-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.c34
-rw-r--r--sys/compat/svr4/imgact_svr4.c26
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
OpenPOWER on IntegriCloud