]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Only unlink from SIEVE LRU if it is still linked
authorOndřej Surý <ondrej@isc.org>
Wed, 29 Oct 2025 06:18:55 +0000 (07:18 +0100)
committerOndřej Surý <ondrej@isc.org>
Tue, 4 Nov 2025 18:52:45 +0000 (19:52 +0100)
Under the overmem conditions, the header could get unlinked from the
SIEVE LRU using a different path.  This could lead to double-unlink
which causes assertion failure.  Add a guard to ISC_SIEVE_UNLINK() to
unlink only still linked headers.

lib/dns/qpcache.c
lib/isc/include/isc/sieve.h

index 4702ff05d862a91a00697b34c9da9e03bb408aad..476559396f0c19a53354ea584da8c90c44616e0b 100644 (file)
@@ -504,7 +504,9 @@ expire_lru_headers(qpcache_t *qpdb, uint32_t idx, size_t requested,
 
                dns_slabtop_t *related = top->related;
 
-               ISC_SIEVE_UNLINK(qpdb->buckets[idx].sieve, top, link);
+               if (ISC_SIEVE_LINKED(top, link)) {
+                       ISC_SIEVE_UNLINK(qpdb->buckets[idx].sieve, top, link);
+               }
 
                dns_slabheader_t *header = first_header(top);
                expired += expireheader(header, nlocktypep, tlocktypep,
@@ -615,7 +617,7 @@ clean_cache_node(qpcache_t *qpdb, qpcnode_t *node) {
 
                        cds_list_del(&top->types_link);
 
-                       if (ISC_LINK_LINKED(top, link)) {
+                       if (ISC_SIEVE_LINKED(top, link)) {
                                ISC_SIEVE_UNLINK(
                                        qpdb->buckets[node->locknum].sieve, top,
                                        link);
@@ -2901,8 +2903,10 @@ add(qpcache_t *qpdb, qpcnode_t *qpnode, dns_slabheader_t *newheader,
                cds_list_add(&newheader->headers_link,
                             &oldheader->top->headers);
 
-               ISC_SIEVE_UNLINK(qpdb->buckets[qpnode->locknum].sieve,
-                                oldheader->top, link);
+               if (ISC_SIEVE_LINKED(oldheader->top, link)) {
+                       ISC_SIEVE_UNLINK(qpdb->buckets[qpnode->locknum].sieve,
+                                        oldheader->top, link);
+               }
 
                qpcache_miss(qpdb, newheader, &nlocktype,
                             &tlocktype DNS__DB_FLARG_PASS);
@@ -3889,7 +3893,7 @@ qpcnode_destroy(qpcnode_t *qpnode) {
                        dns_slabheader_destroy(&header);
                }
 
-               if (ISC_LINK_LINKED(top, link)) {
+               if (ISC_SIEVE_LINKED(top, link)) {
                        ISC_SIEVE_UNLINK(qpdb->buckets[qpnode->locknum].sieve,
                                         top, link);
                }
index f14a1de3bff0d30d53fd654aef228b60ebfab673..bd7a29792b3fe02e2406cccd2b42af7a49e8c325 100644 (file)
                __hand;                                                       \
        })
 
+#define ISC_SIEVE_LINKED(entry, link) ISC_LINK_LINKED(entry, link)
+
 #define ISC_SIEVE_UNLINK(sieve, entry, link)                                 \
        ({                                                                   \
                __typeof__((sieve).hand) __hand = (sieve).hand;              \