]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Remove the memmove call on dns_rbtnode_t structure that contains atomics
authorMark Andrews <marka@isc.org>
Mon, 21 Sep 2020 04:52:53 +0000 (14:52 +1000)
committerMark Andrews <marka@isc.org>
Mon, 21 Sep 2020 09:21:28 +0000 (19:21 +1000)
Calling the plain memmove on the structure that contains atomic members
triggers following TSAN warning (even when we don't really use the
atomic members in the code):

    WARNING: ThreadSanitizer: data race
      Read of size 8 at 0x000000000001 by thread T1 (mutexes: write M1, write M2):
#0 memmove <null>
#1 memmove /usr/include/x86_64-linux-gnu/bits/string_fortified.h:40:10
#2 deletefromlevel lib/dns/rbt.c:2675:3
#3 dns_rbt_deletenode lib/dns/rbt.c:2143:2
#4 delete_node lib/dns/rbtdb.c
#5 decrement_reference lib/dns/rbtdb.c:2202:4
#6 prune_tree lib/dns/rbtdb.c:2259:3
#7 dispatch lib/isc/task.c:1152:7
#8 run lib/isc/task.c:1344:2

      Previous atomic write of size 8 at 0x000000000001 by thread T2 (mutexes: read M3):
#0 __tsan_atomic64_fetch_sub <null>
#1 decrement_reference lib/dns/rbtdb.c:2103:7
#2 detachnode lib/dns/rbtdb.c:5440:6
#3 dns_db_detachnode lib/dns/db.c:588:2
#4 qctx_clean lib/ns/query.c:5104:3
#5 ns_query_done lib/ns/query.c:10868:2
#6 query_sign_nodata lib/ns/query.c
#7 query_nodata lib/ns/query.c:8438:11
#8 query_gotanswer lib/ns/query.c
#9 query_lookup lib/ns/query.c:5624:10
#10 ns__query_start lib/ns/query.c:5500:10
#11 query_setup lib/ns/query.c:5224:11
#12 ns_query_start lib/ns/query.c:11357:8
#13 ns__client_request lib/ns/client.c:2166:3
#14 udp_recv_cb lib/isc/netmgr/udp.c:414:2
#15 uv__udp_recvmsg /home/ondrej/Projects/tsan/libuv/src/unix/udp.c
#16 uv__udp_io /home/ondrej/Projects/tsan/libuv/src/unix/udp.c:180:5
#17 uv__io_poll /home/ondrej/Projects/tsan/libuv/src/unix/linux-core.c:461:11
#18 uv_run /home/ondrej/Projects/tsan/libuv/src/unix/core.c:385:5
#19 nm_thread lib/isc/netmgr/netmgr.c:500:11

      Location is heap block of size 132 at 0x000000000030 allocated by thread T3:
#0 malloc <null>
#1 default_memalloc lib/isc/mem.c:713:8
#2 mem_get lib/isc/mem.c:622:8
#3 mem_allocateunlocked lib/isc/mem.c:1268:8
#4 isc___mem_allocate lib/isc/mem.c:1288:7
#5 isc__mem_allocate lib/isc/mem.c:2453:10
#6 isc___mem_get lib/isc/mem.c:1037:11
#7 isc__mem_get lib/isc/mem.c:2432:10
#8 create_node lib/dns/rbt.c:2239:9
#9 dns_rbt_addnode lib/dns/rbt.c:1435:12
#10 findnodeintree lib/dns/rbtdb.c:2895:12
#11 findnode lib/dns/rbtdb.c:2941:10
#12 dns_db_findnode lib/dns/db.c:439:11
#13 diff_apply lib/dns/diff.c:306:5
#14 dns_diff_apply lib/dns/diff.c:459:10
#15 do_one_tuple lib/ns/update.c:444:11
#16 update_one_rr lib/ns/update.c:495:10
#17 update_action lib/ns/update.c:3123:6
#18 dispatch lib/isc/task.c:1152:7
#19 run lib/isc/task.c:1344:2

      Mutex M1 is already destroyed.

      Mutex M2 is already destroyed.

      Mutex M3 is already destroyed.

      Thread T1 (running) created by main thread at:
#0 pthread_create <null>
#1 isc_thread_create lib/isc/pthreads/thread.c:73:8
#2 isc_taskmgr_create lib/isc/task.c:1434:3
#3 create_managers bin/named/main.c:915:11
#4 setup bin/named/main.c:1223:11
#5 main bin/named/main.c:1523:2

      Thread T2 (running) created by main thread at:
#0 pthread_create <null>
#1 isc_thread_create lib/isc/pthreads/thread.c:73:8
#2 isc_nm_start lib/isc/netmgr/netmgr.c:223:3
#3 create_managers bin/named/main.c:909:15
#4 setup bin/named/main.c:1223:11
#5 main bin/named/main.c:1523:2

      Thread T3 (running) created by main thread at:
#0 pthread_create <null>
#1 isc_thread_create lib/isc/pthreads/thread.c:73:8
#2 isc_taskmgr_create lib/isc/task.c:1434:3
#3 create_managers bin/named/main.c:915:11
#4 setup bin/named/main.c:1223:11
#5 main bin/named/main.c:1523:2

    SUMMARY: ThreadSanitizer: data race in memmove

(cherry picked from commit 48d54368d5fcd36c1d1408dd897774af08c2eb75)

lib/dns/rbt.c

index a7283f0574a66c6e822bdcd9094a311b6310f544..986445459b90ba993d3bf9395c27180c864f9905 100644 (file)
@@ -2637,7 +2637,8 @@ deletefromlevel(dns_rbtnode_t *item, dns_rbtnode_t **rootp) {
                 */
                child = LEFT(item);
        } else {
-               dns_rbtnode_t holder, *tmp = &holder;
+               dns_rbtnode_t *saved_parent, *saved_right;
+               int saved_color;
 
                /*
                 * This node has two children, so it cannot be directly
@@ -2673,7 +2674,9 @@ deletefromlevel(dns_rbtnode_t *item, dns_rbtnode_t **rootp) {
                 * information, which will be needed when linking up
                 * delete to the successor's old location.
                 */
-               memmove(tmp, successor, sizeof(dns_rbtnode_t));
+               saved_parent = PARENT(successor);
+               saved_right = RIGHT(successor);
+               saved_color = COLOR(successor);
 
                if (IS_ROOT(item)) {
                        *rootp = successor;
@@ -2699,28 +2702,27 @@ deletefromlevel(dns_rbtnode_t *item, dns_rbtnode_t **rootp) {
 
                /*
                 * Now relink the node to be deleted into the
-                * successor's previous tree location.  PARENT(tmp)
-                * is the successor's original parent.
+                * successor's previous tree location.
                 */
                INSIST(!IS_ROOT(item));
 
-               if (PARENT(tmp) == item) {
+               if (saved_parent == item) {
                        /*
                         * Node being deleted was successor's parent.
                         */
                        RIGHT(successor) = item;
                        PARENT(item) = successor;
                } else {
-                       LEFT(PARENT(tmp)) = item;
-                       PARENT(item) = PARENT(tmp);
+                       LEFT(saved_parent) = item;
+                       PARENT(item) = saved_parent;
                }
 
                /*
                 * Original location of successor node has no left.
                 */
                LEFT(item) = NULL;
-               RIGHT(item) = RIGHT(tmp);
-               COLOR(item) = COLOR(tmp);
+               RIGHT(item) = saved_right;
+               COLOR(item) = saved_color;
        }
 
        /*