Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 17 Dec 2013 09:21:56 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r259499 - in stable/10/sys: kern vm
Message-ID:  <201312170921.rBH9LunD089563@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Tue Dec 17 09:21:56 2013
New Revision: 259499
URL: http://svnweb.freebsd.org/changeset/base/259499

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/10/sys/kern/vfs_vnops.c
  stable/10/sys/vm/vm_fault.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/kern/vfs_vnops.c
==============================================================================
--- stable/10/sys/kern/vfs_vnops.c	Tue Dec 17 07:59:00 2013	(r259498)
+++ stable/10/sys/kern/vfs_vnops.c	Tue Dec 17 09:21:56 2013	(r259499)
@@ -933,7 +933,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;
@@ -1007,21 +1007,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/10/sys/vm/vm_fault.c
==============================================================================
--- stable/10/sys/vm/vm_fault.c	Tue Dec 17 07:59:00 2013	(r259498)
+++ stable/10/sys/vm/vm_fault.c	Tue Dec 17 09:21:56 2013	(r259499)
@@ -1079,7 +1079,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);
 
 	/*
@@ -1088,9 +1088,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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201312170921.rBH9LunD089563>