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 */
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to