Author: truckman
Date: Mon May 12 07:05:46 2014
New Revision: 265905
URL: http://svnweb.freebsd.org/changeset/base/265905

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/8/sys/kern/subr_rman.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/kern/   (props changed)

Modified: stable/8/sys/kern/subr_rman.c
==============================================================================
--- stable/8/sys/kern/subr_rman.c       Mon May 12 06:14:14 2014        
(r265904)
+++ stable/8/sys/kern/subr_rman.c       Mon May 12 07:05:46 2014        
(r265905)
@@ -451,7 +451,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))
                ;
 
@@ -461,6 +461,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);
        /*
@@ -468,11 +473,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;
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to