]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
4366. [bug] Address race condition when updating rbtnode bit
authorMark Andrews <marka@isc.org>
Tue, 17 May 2016 03:13:45 +0000 (13:13 +1000)
committerMark Andrews <marka@isc.org>
Tue, 17 May 2016 03:17:05 +0000 (13:17 +1000)
                        fields. [RT #42379]

(cherry picked from commit e2047969decfc0c3fc1a946ccade993cab9c9315)

CHANGES
lib/dns/include/dns/rbt.h

diff --git a/CHANGES b/CHANGES
index fc65311c92ce0b8b727b24a89014ee77bfeb1311..7f7d0f03df497b62593c827f1a6a89ca356b86de 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+4366.  [bug]           Address race condition when updating rbtnode bit
+                       fields. [RT #42379]
+
 4363.  [port]          Turn off triggering UAC when running BINDInstall
                        temporarily.
 
index 8a2f0713b2c2141263cbda1aaca17458ee441c83..490cf6f8b74535b12677b7001fb8390955c44a51 100644 (file)
@@ -89,7 +89,18 @@ struct dns_rbtnode {
         *
         * In each case below the "range" indicated is what's _necessary_ for
         * the bitfield to hold, not what it actually _can_ hold.
+        *
+        * Note: Tree lock must be held before modifying these
+        * bit-fields.
+        *
+        * Note: The two "unsigned int :0;" unnamed bitfields on either
+        * side of the bitfields below are scaffolding that border the
+        * set of bitfields which are accessed after acquiring the tree
+        * lock. Please don't insert any other bitfield members between
+        * the unnamed bitfields unless they should also be accessed
+        * after acquiring the tree lock.
         */
+       unsigned int :0;                /* start of bitfields c/o tree lock */
        unsigned int is_root : 1;       /*%< range is 0..1 */
        unsigned int color : 1;         /*%< range is 0..1 */
        unsigned int find_callback : 1; /*%< range is 0..1 */
@@ -102,16 +113,7 @@ struct dns_rbtnode {
 
        /* node needs to be cleaned from rpz */
        unsigned int rpz : 1;
-
-       /*@{*/
-       /*!
-        * These values are used in the RBT DB implementation.  The appropriate
-        * node lock must be held before accessing them.
-        */
-       unsigned int dirty:1;
-       unsigned int wild:1;
-       unsigned int locknum:DNS_RBT_LOCKLENGTH;
-       /*@}*/
+       unsigned int :0;                /* end of bitfields c/o tree lock */
 
 #ifdef DNS_RBT_USEHASH
        unsigned int hashval;
@@ -134,11 +136,30 @@ struct dns_rbtnode {
        /*!
         * These values are used in the RBT DB implementation.  The appropriate
         * node lock must be held before accessing them.
+        *
+        * Note: The two "unsigned int :0;" unnamed bitfields on either
+        * side of the bitfields below are scaffolding that border the
+        * set of bitfields which are accessed after acquiring the node
+        * lock. Please don't insert any other bitfield members between
+        * the unnamed bitfields unless they should also be accessed
+        * after acquiring the node lock.
+        *
+        * NOTE: Do not merge these fields into bitfields above, as
+        * they'll all be put in the same qword that could be accessed
+        * without the node lock as it shares the qword with other
+        * members. Leave these members here so that they occupy a
+        * separate region of memory.
         */
        void *data;
+       unsigned int :0;                /* start of bitfields c/o node lock */
+       unsigned int dirty:1;
+       unsigned int wild:1;
+       unsigned int locknum:DNS_RBT_LOCKLENGTH;
 #ifndef DNS_RBT_USEISCREFCOUNT
        unsigned int references:DNS_RBT_REFLENGTH;
-#else
+#endif
+       unsigned int :0;                /* end of bitfields c/o node lock */
+#ifdef DNS_RBT_USEISCREFCOUNT
        isc_refcount_t references; /* note that this is not in the bitfield */
 #endif
        /*@}*/