Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 16 Aug 2019 21:54:12 +0000 (UTC)
From:      Doug Moore <dougm@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r351150 - stable/12/sys/vm
Message-ID:  <201908162154.x7GLsCZE066129@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: dougm
Date: Fri Aug 16 21:54:12 2019
New Revision: 351150
URL: https://svnweb.freebsd.org/changeset/base/351150

Log:
  MFC r348968:
  Avoid overflow in computing gap sizes.
  
  Approved by: markj (mentor)

Modified:
  stable/12/sys/vm/vm_map.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/vm/vm_map.c
==============================================================================
--- stable/12/sys/vm/vm_map.c	Fri Aug 16 21:40:39 2019	(r351149)
+++ stable/12/sys/vm/vm_map.c	Fri Aug 16 21:54:12 2019	(r351150)
@@ -1645,13 +1645,14 @@ vm_map_findspace(vm_map_t map, vm_offset_t start, vm_s
 {
 	vm_map_entry_t llist, rlist, root, y;
 	vm_size_t left_length;
+	vm_offset_t gap_end;
 
 	/*
 	 * Request must fit within min/max VM address and must avoid
 	 * address wrap.
 	 */
 	start = MAX(start, vm_map_min(map));
-	if (start + length > vm_map_max(map) || start + length < start)
+	if (start >= vm_map_max(map) || length > vm_map_max(map) - start)
 		return (vm_map_max(map) - length + 1);
 
 	/* Empty tree means wide open address space. */
@@ -1659,13 +1660,19 @@ vm_map_findspace(vm_map_t map, vm_offset_t start, vm_s
 		return (start);
 
 	/*
-	 * After splay, if start comes before root node, then there
-	 * must be a gap from start to the root.
+	 * After splay_split, if start is within an entry, push it to the start
+	 * of the following gap.  If rlist is at the end of the gap containing
+	 * start, save the end of that gap in gap_end to see if the gap is big
+	 * enough; otherwise set gap_end to start skip gap-checking and move
+	 * directly to a search of the right subtree.
 	 */
 	root = vm_map_splay_split(map, start, length, &llist, &rlist);
-	if (root != NULL)
+	gap_end = rlist->start;
+	if (root != NULL) {
 		start = root->end;
-	else if (rlist != &map->header) {
+		if (root->right != NULL)
+			gap_end = start;
+	} else if (rlist != &map->header) {
 		root = rlist;
 		rlist = root->left;
 		root->left = NULL;
@@ -1676,18 +1683,9 @@ vm_map_findspace(vm_map_t map, vm_offset_t start, vm_s
 	}
 	vm_map_splay_merge(map, root, llist, rlist);
 	VM_MAP_ASSERT_CONSISTENT(map);
-	if (start + length <= root->start)
+	if (length <= gap_end - start)
 		return (start);
 
-	/*
-	 * Root is the last node that might begin its gap before
-	 * start, and this is the last comparison where address
-	 * wrap might be a problem.
-	 */
-	if (root->right == NULL &&
-	    start + length <= vm_map_max(map))
-		return (start);
-
 	/* With max_free, can immediately tell if no solution. */
 	if (root->right == NULL || length > root->right->max_free)
 		return (vm_map_max(map) - length + 1);
@@ -1804,8 +1802,8 @@ vm_map_alignspace(vm_map_t map, vm_object_t object, vm
 	VM_MAP_ASSERT_LOCKED(map);
 	free_addr = *addr;
 	KASSERT(free_addr == vm_map_findspace(map, free_addr, length),
-	    ("caller failed to provide space %d at address %p",
-	     (int)length, (void*)free_addr));
+	    ("caller failed to provide space %#jx at address %p",
+	     (uintmax_t)length, (void *)free_addr));
 	for (;;) {
 		/*
 		 * At the start of every iteration, the free space at address



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