From 96035a309c56a3a4dfd4921171809b08abcbc2fd Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Tue, 17 May 2016 13:13:45 +1000 Subject: [PATCH] 4366. [bug] Address race condition when updating rbtnode bit fields. [RT #42379] (cherry picked from commit e2047969decfc0c3fc1a946ccade993cab9c9315) --- CHANGES | 3 +++ lib/dns/include/dns/rbt.h | 43 +++++++++++++++++++++++++++++---------- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/CHANGES b/CHANGES index fc65311c92c..7f7d0f03df4 100644 --- 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. diff --git a/lib/dns/include/dns/rbt.h b/lib/dns/include/dns/rbt.h index 8a2f0713b2c..490cf6f8b74 100644 --- a/lib/dns/include/dns/rbt.h +++ b/lib/dns/include/dns/rbt.h @@ -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 /*@}*/ -- 2.47.3