]> 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 14:29:00 +0000 (15: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.

(cherry picked from commit c75575e350684ba2c3603462f654f9897e162be3)

lib/dns/rbtdb.c

index 36404f7996bea7a4afafbd552fb73c2ce155be05..a4fdbd2498fb8430add884d6d4bd5855d0251f77 100644 (file)
@@ -206,7 +206,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;
@@ -1488,6 +1488,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,
                         * mark the time in which the refresh failed.
                         */
                        if ((search->options & DNS_DBFIND_STALEOK) != 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))
                        {
                                /*