]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Extend expire_header() to check node lock type
authorOndřej Surý <ondrej@isc.org>
Thu, 5 Jan 2023 21:26:23 +0000 (22:26 +0100)
committerOndřej Surý <ondrej@isc.org>
Fri, 6 Jan 2023 07:43:16 +0000 (08:43 +0100)
Extend the expire_header() to accept the node lock type as one of the
arguments and check whether the the node lock is always write locked +
fix that bug.

While doing that, it was found that expire_header() invocation in
rdataset_expire() passes `false` as a type of tree lock instead of
`isc_rwlocktype_none`.

(Un)fortunately, both values mapped to 0, so no harm was done, but it
has been fixed nevertheless.

lib/dns/rbtdb.c

index a318b48247fdec1db959a063418b17ae47c906f4..d1fa0a76a11a6a8994ae987dc5b6bb46bcb3dffe 100644 (file)
@@ -714,7 +714,8 @@ static void
 update_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, isc_stdtime_t now);
 static void
 expire_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
-             isc_rwlocktype_t *tlocktypep, expire_t reason);
+             isc_rwlocktype_t *nlocktypep, isc_rwlocktype_t *tlocktypep,
+             expire_t reason);
 static void
 overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, isc_stdtime_t now,
              isc_rwlocktype_t *tlocktypep);
@@ -7086,7 +7087,8 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
                    header->rdh_ttl + STALE_TTL(header, rbtdb) <
                            now - RBTDB_VIRTUAL)
                {
-                       expire_header(rbtdb, header, &tlocktype, expire_ttl);
+                       expire_header(rbtdb, header, &nlocktype, &tlocktype,
+                                     expire_ttl);
                }
 
                /*
@@ -8802,11 +8804,13 @@ rdataset_expire(dns_rdataset_t *rdataset) {
        dns_rbtnode_t *rbtnode = rdataset->private2;
        rdatasetheader_t *header = rdataset->private3;
        isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
+       isc_rwlocktype_t tlocktype = isc_rwlocktype_none;
 
        header--;
        NODE_WRLOCK(&rbtdb->node_locks[rbtnode->locknum].lock, &nlocktype);
-       expire_header(rbtdb, header, false, expire_flush);
+       expire_header(rbtdb, header, &nlocktype, &tlocktype, expire_flush);
        NODE_UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock, &nlocktype);
+       INSIST(tlocktype == isc_rwlocktype_none);
 }
 
 static void
@@ -10178,7 +10182,8 @@ overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, isc_stdtime_t now,
 
                header = isc_heap_element(rbtdb->heaps[locknum], 1);
                if (header && header->rdh_ttl < now - RBTDB_VIRTUAL) {
-                       expire_header(rbtdb, header, tlocktypep, expire_ttl);
+                       expire_header(rbtdb, header, &nlocktype, tlocktypep,
+                                     expire_ttl);
                        purgecount--;
                }
 
@@ -10195,7 +10200,8 @@ overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, isc_stdtime_t now,
                         */
                        ISC_LIST_UNLINK(rbtdb->rdatasets[locknum], header,
                                        link);
-                       expire_header(rbtdb, header, tlocktypep, expire_lru);
+                       expire_header(rbtdb, header, &nlocktype, tlocktypep,
+                                     expire_lru);
                        purgecount--;
                }
 
@@ -10205,13 +10211,15 @@ overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, isc_stdtime_t now,
 
 static void
 expire_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
-             isc_rwlocktype_t *tlocktypep, expire_t reason) {
+             isc_rwlocktype_t *nlocktypep, isc_rwlocktype_t *tlocktypep,
+             expire_t reason) {
        set_ttl(rbtdb, header, 0);
        mark_header_ancient(rbtdb, header);
 
        /*
         * Caller must hold the node (write) lock.
         */
+       INSIST(*nlocktypep == isc_rwlocktype_write);
 
        if (isc_refcount_current(&header->node->references) == 0) {
                isc_rwlocktype_t nlocktype = isc_rwlocktype_write;