]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Fix race condition on check_stale_header
authorDiego Fronza <diego@isc.org>
Wed, 27 Jan 2021 22:09:46 +0000 (19:09 -0300)
committerMatthijs Mekking <matthijs@isc.org>
Fri, 29 Jan 2021 09:29:51 +0000 (10:29 +0100)
This commit fix a race that could happen when two or more threads have
failed to refresh the same RRset, the threads could simultaneously
attempt to update the header->last_refresh_fail_ts field in
check_stale_header, a field used to implement stale-refresh-time.

By making this field atomic we avoid such race.

lib/dns/rbtdb.c

index 83f6e30c7c2b89faa821d8b9e55f13c7d437c71a..26fab2df04fdd158ce171c11b250ae5fe1254ac4 100644 (file)
@@ -205,7 +205,7 @@ typedef struct rdatasetheader {
        rbtdb_rdatatype_t type;
        atomic_uint_least16_t attributes;
        dns_trust_t trust;
-       isc_stdtime_t last_refresh_fail_ts;
+       atomic_uint_fast32_t last_refresh_fail_ts;
        struct noqname *noqname;
        struct noqname *closest;
        unsigned int is_mmapped       : 1;
@@ -1487,6 +1487,7 @@ init_rdataset(dns_rbtdb_t *rbtdb, rdatasetheader_t *h) {
        h->next_is_relative = 0;
        h->node_is_relative = 0;
        atomic_init(&h->attributes, 0);
+       atomic_init(&h->last_refresh_fail_ts, 0);
 
 #ifndef ISC_MUTEX_ATOMICS
        STATIC_ASSERT((sizeof(h->attributes) == 2),
@@ -4571,11 +4572,14 @@ check_stale_header(dns_rbtnode_t *node, rdatasetheader_t *header,
                         * failed.
                         */
                        if ((search->options & DNS_DBFIND_STALESTART) != 0) {
-                               header->last_refresh_fail_ts = search->now;
+                               atomic_store_release(
+                                       &header->last_refresh_fail_ts,
+                                       search->now);
                        } else if ((search->options &
                                    DNS_DBFIND_STALEENABLED) != 0 &&
                                   search->now <
-                                          (header->last_refresh_fail_ts +
+                                          (atomic_load_acquire(
+                                                   &header->last_refresh_fail_ts) +
                                            search->rbtdb->serve_stale_refresh))
                        {
                                /*