aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2023-07-22 20:43:45 +0100
committerRichard Henderson <richard.henderson@linaro.org>2023-07-31 12:19:13 -0700
commit055b86e0f0b4325117055d8d31c49011258f4af3 (patch)
tree465df3f6581ee9c55ade567d051429b022ab8b5b
parent234320cd0573f286b5f5c95ee6d757cf003999e7 (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.c15
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] */