[PATCH] serialize access pci_get_strings function with a mutex

wangjian (AN) wangjian161 at huawei.com
Fri Mar 26 09:36:32 UTC 2021


Ok. I agree.

On 2021/3/26 17:10, Michal Privoznik wrote:
> There's no need to CC random developers - we are subscribed to the list.
> 
> On 3/26/21 4:21 AM, wangjian wrote:> serialize access pci_get_strings function with a mutex.> > nodedev-init thread:
>> nodeStateInitializeEnumerate ->
>>    udevEnumerateDevices->
>>      udevProcessDeviceListEntry ->
>>        udevAddOneDevice ->
>>          udevGetDeviceDetails->
>>            udevProcessPCI ->
>>              udevTranslatePCIIds ->
>>                pci_get_strings -> (libpciaccess)
>>                  find_device_name ->
>>                    populate_vendor ->
>>                      d = realloc( vend->devices, (vend->num_devices + 1), * sizeof( struct pci_device_leaf ) );
>>                      vend->num_devices++;
>>
>> udev-event thread:
>> udevEventHandleThread ->
>>    udevHandleOneDevice ->
>>      udevAddOneDevice->
>>        udevGetDeviceDetails->
>>          udevProcessPCI ->
>>            udevTranslatePCIIds ->
>>              pci_get_strings -> (libpciaccess)
>>                find_device_name ->
>>                  populate_vendor ->
>>                    d = realloc( vend->devices, (vend->num_devices + 1), * sizeof( struct pci_device_leaf ) );
>>                    vend->num_devices++;
>>
>> Since the functions provided by libpciaccess are not thread-safe,
>> when the udev-event and nodedev-init threads of libvirt call
>> the pci_get_strings function provided by libpaciaccess at the same time.
>> It will appear that for the same address, realloc a large space first,
>> and then realloc a small space, which triggers the 'invalid next size' of realloc,
>> leading to the thread core.
>>
>> Signed-off-by: WangJian <wangjian161 at huawei.com>
>> ---
>>   src/node_device/node_device_udev.c | 3 +++
>>   1 file changed, 3 insertions(+)
>>
>> diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
>> index 3f28858..cc752ba 100644
>> --- a/src/node_device/node_device_udev.c
>> +++ b/src/node_device/node_device_udev.c
>> @@ -331,6 +331,7 @@ udevGenerateDeviceName(struct udev_device *device,
>>       return 0;
>>   }
>>
>> +static pthread_mutex_t g_pciaccess_mutex = PTHREAD_MUTEX_INITIALIZER;
> 
> We tend to use virMutex (even though it is pthread_mutex under the hood).
> 
>>
>>   static int
>>   udevTranslatePCIIds(unsigned int vendor,
>> @@ -350,11 +351,13 @@ udevTranslatePCIIds(unsigned int vendor,
>>       m.match_data = 0;
>>
>>       /* pci_get_strings returns void */
>> +    pthread_mutex_lock(&g_pciaccess_mutex);
>>       pci_get_strings(&m,
>>                       &device_name,
>>                       &vendor_name,
>>                       NULL,
>>                       NULL);
>> +    pthread_mutex_unlock(&g_pciaccess_mutex);
>>
>>       *vendor_string = g_strdup(vendor_name);
>>       *product_string = g_strdup(device_name);
>>
> 
> Apart from that, the patch is correct. I'd squash this in and push if you agree:
> 
> diff --git i/src/node_device/node_device_udev.c w/src/node_device/node_device_udev.c
> index cc752bad32..3daa5c90ad 100644
> --- i/src/node_device/node_device_udev.c
> +++ w/src/node_device/node_device_udev.c
> @@ -331,7 +331,7 @@ udevGenerateDeviceName(struct udev_device *device,
>      return 0;
>  }
> 
> -static pthread_mutex_t g_pciaccess_mutex = PTHREAD_MUTEX_INITIALIZER;
> +static virMutex pciaccessMutex = VIR_MUTEX_INITIALIZER;
> 
>  static int
>  udevTranslatePCIIds(unsigned int vendor,
> @@ -350,14 +350,14 @@ udevTranslatePCIIds(unsigned int vendor,
>      m.device_class_mask = 0;
>      m.match_data = 0;
> 
> -    /* pci_get_strings returns void */
> -    pthread_mutex_lock(&g_pciaccess_mutex);
> +    /* pci_get_strings returns void and unfortunately is not thread safe. */
> +    virMutexLock(&pciaccessMutex);
>      pci_get_strings(&m,
>                      &device_name,
>                      &vendor_name,
>                      NULL,
>                      NULL);
> -    pthread_mutex_unlock(&g_pciaccess_mutex);
> +    virMutexUnlock(&pciaccessMutex);
> 
>      *vendor_string = g_strdup(vendor_name);
>      *product_string = g_strdup(device_name);
> 
> 
> Michal
> 
> .
> 




More information about the libvir-list mailing list