[libvirt] [PATCH 08/10] qemuDomainCreateDevice: Don't loop endlessly

Michal Privoznik mprivozn at redhat.com
Tue Feb 7 11:20:29 UTC 2017


On 02/07/2017 11:34 AM, Martin Kletzander wrote:
> On Fri, Jan 20, 2017 at 10:42:48AM +0100, Michal Privoznik wrote:
>> When working with symlinks it is fairly easy to get into a loop.
>> Don't.
>>
>> Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
>> ---
>> src/qemu/qemu_domain.c | 28 ++++++++++++++++++++++++----
>> 1 file changed, 24 insertions(+), 4 deletions(-)
>>
>> diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
>> index 8cbfb2d16..448583313 100644
>> --- a/src/qemu/qemu_domain.c
>> +++ b/src/qemu/qemu_domain.c
>> @@ -6954,9 +6954,10 @@ qemuDomainGetPreservedMounts(virQEMUDriverPtr
>> driver,
>>
>>
>> static int
>> -qemuDomainCreateDevice(const char *device,
>> -                       const char *path,
>> -                       bool allow_noent)
>> +qemuDomainCreateDeviceRecursive(const char *device,
>> +                                const char *path,
>> +                                bool allow_noent,
>> +                                unsigned int ttl)
>> {
>>     char *devicePath = NULL;
>>     char *target = NULL;
>> @@ -6968,6 +6969,13 @@ qemuDomainCreateDevice(const char *device,
>>     char *tcon = NULL;
>> #endif
>>
>> +    if (!ttl) {
>> +        virReportSystemError(ELOOP,
>> +                             _("Too many levels of symbolic links: %s"),
>> +                             device);
>> +        return ret;
>> +    }
>> +
>>     if (lstat(device, &sb) < 0) {
>>         if (errno == ENOENT && allow_noent) {
>>             /* Ignore non-existent device. */
>> @@ -7057,7 +7065,8 @@ qemuDomainCreateDevice(const char *device,
>>             tmp = NULL;
>>         }
>>
>> -        if (qemuDomainCreateDevice(target, path, allow_noent) < 0)
>> +        if (qemuDomainCreateDeviceRecursive(target, path,
>> +                                            allow_noent, ttl - 1) < 0)
>>             goto cleanup;
>>     } else {
>>         if (create &&
>> @@ -7128,6 +7137,17 @@ qemuDomainCreateDevice(const char *device,
>> }
>>
>>
>> +static int
>> +qemuDomainCreateDevice(const char *device,
>> +                       const char *path,
>> +                       bool allow_noent)
>> +{
>> +    long symloop_max = sysconf(_SC_SYMLOOP_MAX);
>> +
>> +    return qemuDomainCreateDeviceRecursive(device, path,
>> +                                           allow_noent, symloop_max);
> 
> So you are taking 'long' that can, officially, be '-1' and pass it to a
> function as unsigned int.  Having a maximum is nice, I have no idea why
> on my system there is no limit apparently (sysconf() returns -1 with no
> errno set), but if the system doesn't report any (like my case above) it
> effectively makes the SYMLOOP_MAX = UINT_MAX in this codepath.  Should
> we avoid that or just let it be?  This way it's still better than
> unlimited, so ACK to this version, but I just wanted a (short)
> discussion about this.

Sure. I think it's safe to assume if the level of symlinks reaches
UINT_MAX your system is terribly broken.

Michal




More information about the libvir-list mailing list