Hi Aaron,

On Wed, Sep 30, 2026 at 03:06:47PM -0400, Aaron Merey wrote:
> 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.

This looks correct.

All tsearch/tfind calls on locs_tree are in dwarf_getlocation.c. One
tsearch in dwarf_getlocation_implicit_value without the cu intern_lock
held. One tfind/tsearch pair in is_constant_offset with the
intern_lock held.

> 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;
>  }

OK.

Thanks,

Mark

Reply via email to