locs_tree is modified by three calls to eu_tsearch_nolock, each of which occurs when intern_lock mutex is held. All calls to eu_tfind* on locs_tree occur when intern_lock is held except one, resulting in a data race.
Fix this by changing this eu_tfind to eu_tfind_nolock and acquiring intern_lock before it is called. Signed-off-by: Aaron Merey <[email protected]> --- libdw/dwarf_getlocation.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c index 6d7296f8..89f09874 100644 --- a/libdw/dwarf_getlocation.c +++ b/libdw/dwarf_getlocation.c @@ -166,17 +166,22 @@ dwarf_getlocation_implicit_value (Dwarf_Attribute *attr, const Dwarf_Op *op, if (attr == NULL) return -1; + mutex_lock (attr->cu->intern_lock); + struct loc_block_s fake = { .addr = (void *) op }; - struct loc_block_s **found = eu_tfind (&fake, &attr->cu->locs_tree, - loc_compare); + struct loc_block_s **found = eu_tfind_nolock (&fake, &attr->cu->locs_tree, + loc_compare); if (unlikely (found == NULL)) { + mutex_unlock (attr->cu->intern_lock); __libdw_seterrno (DWARF_E_NO_BLOCK); return -1; } return_block->length = (*found)->length; return_block->data = (*found)->data; + + mutex_unlock (attr->cu->intern_lock); return 0; } -- 2.55.0
