summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2009-10-13 20:53:42 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2009-10-13 20:53:42 +0000
commit312f6f4f7fb0a11a16d3427a86bb7a888ff29e0a (patch)
tree83968ff654d361628a251ad1f0a79c2d03cbaa45
parent6682179a1c327ebfd5a91e7dc39282434a805c2f (diff)
Make sure we do not loop when allocating an extent region with EX_CONFLICTOK
and the whole extent is used; the current code computations would wrap. Found the hard way by jsg@, fix discuss with kettenis@, and you get a regress test for free (which will spin if you compile it again an old subr_extent.c)
-rw-r--r--regress/sys/kern/extent/extest.exp5
-rw-r--r--regress/sys/kern/extent/tests8
-rw-r--r--sys/kern/subr_extent.c18
3 files changed, 22 insertions, 9 deletions
diff --git a/regress/sys/kern/extent/extest.exp b/regress/sys/kern/extent/extest.exp
index 6312307f2e9..4e4f6a5a462 100644
--- a/regress/sys/kern/extent/extest.exp
+++ b/regress/sys/kern/extent/extest.exp
@@ -1,4 +1,4 @@
-# $OpenBSD: extest.exp,v 1.3 2009/09/18 19:19:15 kettenis Exp $
+# $OpenBSD: extest.exp,v 1.4 2009/10/13 20:53:40 miod Exp $
# $NetBSD: extest.exp,v 1.9 2005/03/15 18:27:23 bouyer Exp $
# real output must start in line 5
@@ -89,3 +89,6 @@ extent `test15' (0x0 - 0xffffffff), flags = 0x0
output for test16
extent `test16' (0x0 - 0xffffffff), flags = 0x0
0x0 - 0x1fffffff
+output for test17
+extent `test17' (0x0 - 0xffffffffffffffff), flags = 0x0
+ 0x0 - 0xffffffffffffffff
diff --git a/regress/sys/kern/extent/tests b/regress/sys/kern/extent/tests
index fe312a5ae4d..9f85853aade 100644
--- a/regress/sys/kern/extent/tests
+++ b/regress/sys/kern/extent/tests
@@ -1,4 +1,4 @@
-# $OpenBSD: tests,v 1.4 2009/09/18 19:19:15 kettenis Exp $
+# $OpenBSD: tests,v 1.5 2009/10/13 20:53:40 miod Exp $
# $NetBSD: tests,v 1.9 2005/03/15 18:27:23 bouyer Exp $
#fill up an extent, should coalesce into one allocation
@@ -130,3 +130,9 @@ alloc_region 0x0 0xa0000
alloc_region 0xf0000 0x1ff10000
alloc_region 0xa0000 0x60000 EX_CONFLICTOK
print
+
+# Check allocation of a conflicting region in an otherwise filled
+# extent does not trigger an infinite loop
+extent test17 0x00000000 -1L EX_FILLED
+alloc_region 0 0x4000 EX_CONFLICTOK
+print
diff --git a/sys/kern/subr_extent.c b/sys/kern/subr_extent.c
index b36408e4ee0..b56fc8a35a3 100644
--- a/sys/kern/subr_extent.c
+++ b/sys/kern/subr_extent.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: subr_extent.c,v 1.40 2009/09/18 22:16:28 kettenis Exp $ */
+/* $OpenBSD: subr_extent.c,v 1.41 2009/10/13 20:53:41 miod Exp $ */
/* $NetBSD: subr_extent.c,v 1.7 1996/11/21 18:46:34 cgd Exp $ */
/*-
@@ -523,17 +523,21 @@ extent_alloc_region(struct extent *ex, u_long start, u_long size, int flags)
* region. We're done.
*/
if (rp->er_start <= start) {
- start = rp->er_end + 1;
- size = end - start + 1;
- goto alloc_start;
+ if (rp->er_end < ex->ex_end) {
+ start = rp->er_end + 1;
+ size = end - start + 1;
+ goto alloc_start;
+ }
} else if (rp->er_end < end) {
LIST_REMOVE(rp, er_link);
extent_free_region_descriptor(ex, rp);
goto alloc_start;
} else if (rp->er_start < end) {
- end = rp->er_start - 1;
- size = end - start + 1;
- goto alloc_start;
+ if (rp->er_start > ex->ex_start) {
+ end = rp->er_start - 1;
+ size = end - start + 1;
+ goto alloc_start;
+ }
}
return (0);
}