[libvirt] [PATCH] qemu: Search binaries in PATH instead of hardcoding /usr/bin

Matthias Bolte matthias.bolte at googlemail.com
Mon Jan 25 20:46:30 UTC 2010


2010/1/22 Matthias Bolte <matthias.bolte at googlemail.com>:
> 2010/1/22 Daniel P. Berrange <berrange at redhat.com>:
>> On Wed, Jan 20, 2010 at 02:46:10AM +0100, Matthias Bolte wrote:
>>> @@ -792,16 +797,30 @@ qemudCapsInitGuest(virCapsPtr caps,
>>>       */
>>>      if (STREQ(info->arch, hostmachine) ||
>>>          (STREQ(hostmachine, "x86_64") && STREQ(info->arch, "i686"))) {
>>> -        const char *const kvmbins[] = { "/usr/bin/qemu-kvm", /* Fedora */
>>> -                                        "/usr/bin/kvm" }; /* Upstream .spec */
>>> +        if (access("/dev/kvm", F_OK) == 0) {
>>> +            const char *const kvmbins[] = { "qemu-kvm", /* Fedora */
>>> +                                            "kvm" }; /* Upstream .spec */
>>> +
>>> +            for (i = 0; i < ARRAY_CARDINALITY(kvmbins); ++i) {
>>> +                kvmbin = virFindFileInPath(kvmbins[i]);
>>> +
>>> +                if (kvmbin == NULL || access(kvmbin, X_OK) != 0) {
>>> +                    VIR_FREE(kvmbin);
>>> +                    continue;
>>> +                }
>>>
>>> -        for (i = 0; i < ARRAY_CARDINALITY(kvmbins); ++i) {
>>> -            if (access(kvmbins[i], X_OK) == 0 &&
>>> -                access("/dev/kvm", F_OK) == 0) {
>>>                  haskvm = 1;
>>> -                kvmbin = kvmbins[i];
>>> -                if (!binary)
>>> -                    binary = kvmbin;
>>> +
>>> +                if (binary == NULL) {
>>> +                    binary = strdup(kvmbin);
>>
>> Why does this need to strdup(kvmbin), when virFindFileInPath() is
>> already returning a newly allocated string ?  Seems like we could
>> just avoid that
>
> The common case is binary pointing to a QEMU binary and if KVM could
> be used and is available kvmbin points to a KVM enabled QEMU binary.
> So the paths a different in the common case. In the cleanup section
> both strings need to be freed.
>
> The special case is if binary is NULL but we find a KVM binary, then
> binary is strdup'ed from kvmbin. Before this patch binary and kvmbin
> were stack allocated and binary = kvmbin was okay. Now binary = kvmbin
> would result in a double free with
>
>    VIR_FREE(binary);
>    VIR_FREE(kvmbin);
>
> But you're right, I just thought about it and
>
>    binary = strdup(kvmbin);
>
> could be changed back to
>
>    binary = kvmbin;
>
> and the cleanup code could be changed to
>
>    if (binary == kvmbin) {
>        /* don't double free */
>        VIR_FREE(binary);
>    } else {
>        VIR_FREE(binary);
>        VIR_FREE(kvmbin);
>    }
>
> to avoid a double free.
>
>>> +
>>> +                    if (binary == NULL) {
>>> +                        virReportOOMError(NULL);
>>> +                        VIR_FREE(kvmbin);
>>> +                        return -1;
>>> +                    }
>>> +                }
>>> +
>>>                  break;
>>>              }
>>
>> I think this loop is also leaking 'kvmbin', since it just
>> overrwrites 'kvmbin' on each iteration, the final cleanup
>> code will only free the last one that was allocated
>
> No leak here. The for loop can be left at 3 points:
>
> - continue; if binary not found or not executable
> - return -1; on OOM error
> - break; on success
>
> In both negative cases kvmbin is freed.
>
>>> -                return -1;
>>> +                goto error;
>>>          }
>>>      }
>>>
>>> +    VIR_FREE(binary);
>>> +    VIR_FREE(kvmbin);
>>> +
>>>      return 0;
>>> +
>>> +no_memory:
>>> +    virReportOOMError(NULL);
>>> +
>>> +error:
>>> +    VIR_FREE(binary);
>>> +    VIR_FREE(kvmbin);
>>> +    virCapabilitiesFreeMachines(machines, nmachines);
>>> +
>>> +    return -1;
>>>  }
>>>
>>
>>
>> Generally the patch looks OK though
>>
>> Daniel
>>
>
> Version 2 of the patch is attached.
>
> Matthias
>

Okay, pushed version 2.

Matthias




More information about the libvir-list mailing list