Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 27 Jul 2021 01:49:36 GMT
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: f065d0bb299b - stable/13 - blist: Correct the node count computed in blist_create()
Message-ID:  <202107270149.16R1na8S067384@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=f065d0bb299bcedf1adc003397d340f88688ff75

commit f065d0bb299bcedf1adc003397d340f88688ff75
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2021-07-13 21:47:27 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2021-07-27 01:47:20 +0000

    blist: Correct the node count computed in blist_create()
    
    Commit bb4a27f927a1 added the ability to allocate a span of blocks
    crossing a meta node boundary.  To ensure that blst_next_leaf_alloc()
    does not walk past the end of the tree, an extra all-zero meta node
    needs to be present at the end of the allocation, and
    blst_next_leaf_alloc() is implemented such that the presence of this
    node terminates the search.
    
    blist_create() computes the number of nodes required.  It had two
    problems:
    1. When the size of the blist is a power of BLIST_RADIX, we would
       unnecessarily allocate an extra level in the tree.
    2. When the size of the blist is a multiple of BLIST_RADIX, we would
       fail to allocate a terminator node.  In this case,
       blst_next_leaf_alloc() could scan beyond the bounds of the
       allocation.  This was found using KASAN.
    
    Modify blist_create() to handle these cases correctly.
    
    Reported by:    pho
    Reviewed by:    dougm
    
    (cherry picked from commit 2783335caeae964bd8a1aa15726b523876613e45)
---
 sys/kern/subr_blist.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/sys/kern/subr_blist.c b/sys/kern/subr_blist.c
index 27b226fd8a18..ba13fb4efd80 100644
--- a/sys/kern/subr_blist.c
+++ b/sys/kern/subr_blist.c
@@ -244,8 +244,16 @@ blist_create(daddr_t blocks, int flags)
 	 * Calculate the radix and node count used for scanning.
 	 */
 	nodes = 1;
-	for (radix = 1; radix <= blocks / BLIST_RADIX; radix *= BLIST_RADIX)
-		nodes += 1 + (blocks - 1) / radix / BLIST_RADIX;
+	for (radix = 1; (blocks - 1) / BLIST_RADIX / radix > 0;
+	    radix *= BLIST_RADIX)
+		nodes += 1 + (blocks - 1) / BLIST_RADIX / radix;
+
+	/*
+	 * Include a sentinel node to ensure that cross-leaf scans stay within
+	 * the bounds of the allocation.
+	 */
+	if (blocks % BLIST_RADIX == 0)
+		nodes++;
 
 	bl = malloc(offsetof(struct blist, bl_root[nodes]), M_SWAP, flags |
 	    M_ZERO);



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