Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 12 May 2014 04:27:10 +0000 (UTC)
From:      Don Lewis <truckman@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: r265901 - stable/10/sys/kern
Message-ID:  <201405120427.s4C4RAZf093033@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: truckman
Date: Mon May 12 04:27:10 2014
New Revision: 265901
URL: http://svnweb.freebsd.org/changeset/base/265901

Log:
  MFC r265363
  
  Avoid unsigned integer overflow which can cause
  rman_reserve_resource_bound() to return incorrect results.
  
  Continue the initial search until the first viable region is found.
  
  Add a comment to explain the search termination test.
  
  PR:		kern/188534
  Reviewed by:	jhb (previous version)

Modified:
  stable/10/sys/kern/subr_rman.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/kern/subr_rman.c
==============================================================================
--- stable/10/sys/kern/subr_rman.c	Mon May 12 02:56:27 2014	(r265900)
+++ stable/10/sys/kern/subr_rman.c	Mon May 12 04:27:10 2014	(r265901)
@@ -456,7 +456,7 @@ rman_reserve_resource_bound(struct rman 
 	mtx_lock(rm->rm_mtx);
 
 	for (r = TAILQ_FIRST(&rm->rm_list);
-	     r && r->r_end < start;
+	     r && r->r_end < start + count - 1;
 	     r = TAILQ_NEXT(r, r_link))
 		;
 
@@ -466,6 +466,11 @@ rman_reserve_resource_bound(struct rman 
 	}
 
 	amask = (1ul << RF_ALIGNMENT(flags)) - 1;
+	if (start + amask < start) {
+		DPRINTF(("start+amask wrapped around\n"));
+		goto out;
+	}
+
 	/* If bound is 0, bmask will also be 0 */
 	bmask = ~(bound - 1);
 	/*
@@ -473,11 +478,20 @@ rman_reserve_resource_bound(struct rman 
 	 */
 	for (s = r; s; s = TAILQ_NEXT(s, r_link)) {
 		DPRINTF(("considering [%#lx, %#lx]\n", s->r_start, s->r_end));
-		if (s->r_start + count - 1 > end) {
+		/*
+		 * The resource list is sorted, so there is no point in
+		 * searching further once r_start is too large.
+		 */
+		if (s->r_start > end - (count - 1)) {
 			DPRINTF(("s->r_start (%#lx) + count - 1> end (%#lx)\n",
 			    s->r_start, end));
 			break;
 		}
+		if (s->r_start + amask < s->r_start) {
+			DPRINTF(("s->r_start (%#lx) + amask (%#lx) wrapped\n",
+			    s->r_start, amask));
+			break;
+		}
 		if (s->r_flags & RF_ALLOCATED) {
 			DPRINTF(("region is allocated\n"));
 			continue;



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