diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2009-10-13 20:53:42 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2009-10-13 20:53:42 +0000 |
commit | 312f6f4f7fb0a11a16d3427a86bb7a888ff29e0a (patch) | |
tree | 83968ff654d361628a251ad1f0a79c2d03cbaa45 | |
parent | 6682179a1c327ebfd5a91e7dc39282434a805c2f (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.exp | 5 | ||||
-rw-r--r-- | regress/sys/kern/extent/tests | 8 | ||||
-rw-r--r-- | sys/kern/subr_extent.c | 18 |
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); } |