Author: kib
Date: Tue Dec 17 09:22:25 2013
New Revision: 259500
URL: http://svnweb.freebsd.org/changeset/base/259500

Log:
  MFC r258039:
  Avoid overflow for the page counts.
  
  MFC r258365:
  Revert back to use int for the page counts.
  Rearrange the checks to correctly handle overflowing address arithmetic.

Modified:
  stable/9/sys/kern/vfs_vnops.c
  stable/9/sys/vm/vm_fault.c
Directory Properties:
  stable/9/sys/   (props changed)

Modified: stable/9/sys/kern/vfs_vnops.c
==============================================================================
--- stable/9/sys/kern/vfs_vnops.c       Tue Dec 17 09:21:56 2013        
(r259499)
+++ stable/9/sys/kern/vfs_vnops.c       Tue Dec 17 09:22:25 2013        
(r259500)
@@ -891,7 +891,7 @@ vn_io_fault(struct file *fp, struct uio 
        void *rl_cookie;
        struct mount *mp;
        vm_page_t *prev_td_ma;
-       int cnt, error, save, saveheld, prev_td_ma_cnt;
+       int error, cnt, save, saveheld, prev_td_ma_cnt;
        vm_offset_t addr, end;
        vm_prot_t prot;
        size_t len, resid;
@@ -965,21 +965,20 @@ vn_io_fault(struct file *fp, struct uio 
                        uio_clone->uio_iovcnt--;
                        continue;
                }
-
-               addr = (vm_offset_t)uio_clone->uio_iov->iov_base;
+               if (len > io_hold_cnt * PAGE_SIZE)
+                       len = io_hold_cnt * PAGE_SIZE;
+               addr = (uintptr_t)uio_clone->uio_iov->iov_base;
                end = round_page(addr + len);
-               cnt = howmany(end - trunc_page(addr), PAGE_SIZE);
+               if (end < addr) {
+                       error = EFAULT;
+                       break;
+               }
+               cnt = atop(end - trunc_page(addr));
                /*
                 * A perfectly misaligned address and length could cause
                 * both the start and the end of the chunk to use partial
                 * page.  +2 accounts for such a situation.
                 */
-               if (cnt > io_hold_cnt + 2) {
-                       len = io_hold_cnt * PAGE_SIZE;
-                       KASSERT(howmany(round_page(addr + len) -
-                           trunc_page(addr), PAGE_SIZE) <= io_hold_cnt + 2,
-                           ("cnt overflow"));
-               }
                cnt = vm_fault_quick_hold_pages(&td->td_proc->p_vmspace->vm_map,
                    addr, len, prot, ma, io_hold_cnt + 2);
                if (cnt == -1) {

Modified: stable/9/sys/vm/vm_fault.c
==============================================================================
--- stable/9/sys/vm/vm_fault.c  Tue Dec 17 09:21:56 2013        (r259499)
+++ stable/9/sys/vm/vm_fault.c  Tue Dec 17 09:22:25 2013        (r259500)
@@ -1121,7 +1121,7 @@ vm_fault_quick_hold_pages(vm_map_t map, 
 
        if (len == 0)
                return (0);
-       end = round_page(addr + len);   
+       end = round_page(addr + len);
        addr = trunc_page(addr);
 
        /*
@@ -1130,9 +1130,9 @@ vm_fault_quick_hold_pages(vm_map_t map, 
        if (addr < vm_map_min(map) || addr > end || end > vm_map_max(map))
                return (-1);
 
-       count = howmany(end - addr, PAGE_SIZE);
-       if (count > max_count)
+       if (atop(end - addr) > max_count)
                panic("vm_fault_quick_hold_pages: count > max_count");
+       count = atop(end - addr);
 
        /*
         * Most likely, the physical pages are resident in the pmap, so it is
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-stable-9
To unsubscribe, send any mail to "[email protected]"

Reply via email to