]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Make __libdwfl_debuginfod_find_* functions thread safe
authorAaron Merey <amerey@redhat.com>
Fri, 19 Dec 2025 22:39:36 +0000 (17:39 -0500)
committerAaron Merey <amerey@redhat.com>
Tue, 3 Feb 2026 15:31:48 +0000 (10:31 -0500)
Individual debuginfod_client objects and their underlying CURLM handles
should not be used concurrently during calls to
__libdwfl_debuginfod_find_debuginfo and
__libdwfl_debuginfod_find_executable.

Add a mutex field to struct Dwfl to serialize calls to
__libdwfl_debuginfod_find_*.

Signed-off-by: Aaron Merey <amerey@redhat.com>
libdwfl/debuginfod-client.c
libdwfl/dwfl_begin.c
libdwfl/dwfl_end.c
libdwfl/libdwfl.h
libdwfl/libdwflP.h

index 882a5efff9bbc622c0fcce90c021b18530b341ec..ecb053fc048f2d23cf0589817722c683579ffb1e 100644 (file)
@@ -49,7 +49,7 @@ static void __libdwfl_debuginfod_init (void);
 
 static pthread_once_t init_control = PTHREAD_ONCE_INIT;
 
-/* NB: this is slightly thread-unsafe */
+/* dwfl->debuginfod_lock must be held when calling this function.  */
 
 debuginfod_client *
 dwfl_get_debuginfod_client (Dwfl *dwfl)
@@ -77,10 +77,12 @@ __libdwfl_debuginfod_find_executable (Dwfl *dwfl,
   int fd = -1;
   if (build_id_len > 0)
     {
+      mutex_lock (dwfl->debuginfod_lock);
       debuginfod_client *c = INTUSE (dwfl_get_debuginfod_client) (dwfl);
       if (c != NULL)
        fd = (*fp_debuginfod_find_executable) (c, build_id_bits,
                                               build_id_len, NULL);
+      mutex_unlock (dwfl->debuginfod_lock);
     }
 
   return fd;
@@ -94,10 +96,12 @@ __libdwfl_debuginfod_find_debuginfo (Dwfl *dwfl,
   int fd = -1;
   if (build_id_len > 0)
     {
+      mutex_lock (dwfl->debuginfod_lock);
       debuginfod_client *c = INTUSE (dwfl_get_debuginfod_client) (dwfl);
       if (c != NULL)
        fd = (*fp_debuginfod_find_debuginfo) (c, build_id_bits,
                                              build_id_len, NULL);
+      mutex_unlock (dwfl->debuginfod_lock);
     }
 
   return fd;
index b03f5cf4b339c1439b1d149851ced80bac5c10d6..835de8e32f895554b5cb2a2b2aad51c28000a6c7 100644 (file)
@@ -50,6 +50,8 @@ dwfl_begin (const Dwfl_Callbacks *callbacks)
       dwfl->offline_next_address = OFFLINE_REDZONE;
     }
 
+  mutex_init (dwfl->debuginfod_lock);
+
   return dwfl;
 }
 INTDEF (dwfl_begin)
index d9cf569b1f7b20b00d19a2bb7e7178a4abcbc4bc..c82d83fbc756d5aad741ad5f51d46a06dfeb45e1 100644 (file)
@@ -53,6 +53,7 @@ dwfl_end (Dwfl *dwfl)
   free (dwfl->lookup_module);
   free (dwfl->lookup_segndx);
   free (dwfl->sysroot);
+  mutex_fini (dwfl->debuginfod_lock);
 
   Dwfl_Module *next = dwfl->modulelist;
   while (next != NULL)
index 90523283c9359b09a16709a8422917a44257932f..4064082dd596f0ec5a8c0baf20a7b9a2c196653e 100644 (file)
@@ -835,6 +835,9 @@ int dwfl_frame_reg (Dwfl_Frame *state, unsigned regno, Dwarf_Word *val)
    When the client connection has not yet been initialized, it will be done on the
    first call to this function. If elfutils is compiled without support for debuginfod,
    NULL will be returned.
+
+   The returned debuginfod-client handle must not be used at the same time as
+   any libdwfl function taking the client's associated DWFL as an argument.
  */
 extern debuginfod_client *dwfl_get_debuginfod_client (Dwfl *dwfl);
 
index a5d88d6050b9eb1383d7cda9dca128286cc165fb..6e394c26201073599caa83102cf4039a2743cd6f 100644 (file)
@@ -141,6 +141,9 @@ struct Dwfl
   struct Dwfl_User_Core *user_core;
   char *sysroot;               /* sysroot, or NULL to search standard system
                                   paths */
+
+  /* Serialize debuginfod_client usage.  */
+  mutex_define (, debuginfod_lock);
 };
 
 #define OFFLINE_REDZONE                0x10000