diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2023-07-22 20:43:45 +0100 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2023-07-31 12:19:13 -0700 |
commit | 055b86e0f0b4325117055d8d31c49011258f4af3 (patch) | |
tree | 465df3f6581ee9c55ade567d051429b022ab8b5b | |
parent | 234320cd0573f286b5f5c95ee6d757cf003999e7 (diff) |
util/interval-tree: Use qatomic_read for left/right while searching
Fixes a race condition (generally without optimization) in which
the subtree is re-read after the protecting if condition.
Cc: qemu-stable@nongnu.org
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r-- | util/interval-tree.c | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/util/interval-tree.c b/util/interval-tree.c index 4c0baf108f..5a0ad21b2d 100644 --- a/util/interval-tree.c +++ b/util/interval-tree.c @@ -745,8 +745,9 @@ static IntervalTreeNode *interval_tree_subtree_search(IntervalTreeNode *node, * Loop invariant: start <= node->subtree_last * (Cond2 is satisfied by one of the subtree nodes) */ - if (node->rb.rb_left) { - IntervalTreeNode *left = rb_to_itree(node->rb.rb_left); + RBNode *tmp = qatomic_read(&node->rb.rb_left); + if (tmp) { + IntervalTreeNode *left = rb_to_itree(tmp); if (start <= left->subtree_last) { /* @@ -765,8 +766,9 @@ static IntervalTreeNode *interval_tree_subtree_search(IntervalTreeNode *node, if (start <= node->last) { /* Cond2 */ return node; /* node is leftmost match */ } - if (node->rb.rb_right) { - node = rb_to_itree(node->rb.rb_right); + tmp = qatomic_read(&node->rb.rb_right); + if (tmp) { + node = rb_to_itree(tmp); if (start <= node->subtree_last) { continue; } @@ -814,8 +816,9 @@ IntervalTreeNode *interval_tree_iter_first(IntervalTreeRoot *root, IntervalTreeNode *interval_tree_iter_next(IntervalTreeNode *node, uint64_t start, uint64_t last) { - RBNode *rb = node->rb.rb_right, *prev; + RBNode *rb, *prev; + rb = qatomic_read(&node->rb.rb_right); while (true) { /* * Loop invariants: @@ -840,7 +843,7 @@ IntervalTreeNode *interval_tree_iter_next(IntervalTreeNode *node, } prev = &node->rb; node = rb_to_itree(rb); - rb = node->rb.rb_right; + rb = qatomic_read(&node->rb.rb_right); } while (prev == rb); /* Check if the node intersects [start;last] */ |