--- a/sys/kern/subr_alist.c +++ b/sys/kern/subr_alist.c @@ -146,6 +146,9 @@ alist_blk_t radix; alist_blk_t skip = 0; + if (blocks == 0 || blocks > ALIST_BLOCKS_MAX) + return(NULL); + /* * Calculate radix and skip field used for scanning. */ @@ -190,6 +193,9 @@ alist_blk_t radix; alist_blk_t skip = 0; + if (blocks == 0 || blocks > ALIST_BLOCKS_MAX) + panic("alist_init: invalid block count %d", blocks); + /* * Calculate radix and skip field used for scanning. */ @@ -245,9 +251,12 @@ alist_blk_t blk = ALIST_BLOCK_NONE; /* - * Check non power-of-2 + * Check non power-of-2. NOTE: count == 0 must be rejected + * explicitly, the power-of-2 test below cannot distinguish it + * and the allocator arithmetic is undefined for it. */ - KKASSERT(count); + if (count == 0) + return(ALIST_BLOCK_NONE); if ((count | (count - 1)) != (count << 1) - 1) { alist_blk_t ncount = (count < 256) ? 1 : 256; while (ncount < count) @@ -261,7 +270,7 @@ /* * Power of 2 */ - if (bl && count < bl->bl_radix) { + if (bl && count <= bl->bl_radix) { if (bl->bl_radix == ALIST_BMAP_RADIX) { blk = alst_leaf_alloc(bl->bl_root, 0, start, count); } else { --- a/sys/sys/alist.h +++ b/sys/sys/alist.h @@ -92,6 +92,12 @@ #define ALIST_BLOCK_NONE ((alist_blk_t)-1) /* + * Largest block count whose radix computation cannot wrap + * (32 * 16^6 = 2^29; anything larger overflows alist_blk_t). + */ +#define ALIST_BLOCKS_MAX ((alist_blk_t)1 << 29) + +/* * When alist_init() is used the caller can pre-allocate the records * array. */