• L
    util: refactor virNetlinkCommand to fix several bugs / style problems · 5d85b8a8
    Laine Stump 提交于
    Inspired by a simpler patch from "Wangrui (K) <moon.wangrui@huawei.com>".
    
    A submitted patch pointed out that virNetlinkCommand() was doing an
    improper typecast of the return value from nl_recv() (int to
    unsigned), causing it to miss error returns, and that even after
    remedying that problem, virNetlinkCommand() was calling VIR_FREE() on
    the pointer returned from nl_recv() (*resp) even if nl_recv() had
    returned an error, and that in this case the pointer was verifiably
    invalid, as it was pointing to memory that had been allocated by
    libnl, but then freed prior to returning the error.
    
    While reviewing this patch, I noticed several other problems with this
    seemingly simple function (at least one of them as serious as the
    problem being reported/fixed by the aforementioned patch), and decided
    they all deserved to be fixed. Here is the list:
    
    1) The return value from nl_recv() must be assigned to an int (rather
       than unsigned int) in order to detect failure.
    
    2) When nl_recv() returns an error or 0, the contents of *resp is
       invalid, and should be simply set to 0, *not* VIR_FREE()'d.
    
    3) When nl_recv() returns 0, errno is not set, so the logged error
       message should not reference errno (it *is* an error though).
    
    4) The first error return from virNetlinkCommand returns -EINVAL,
       incorrectly implying that the caller can expect the return value to
       be of the "-errno" variety, which is not true in any other case.
    
    5) The 2nd error return returns directly with garbage in *resp. While
       the caller should never use *resp in this case, it's still good
       practice to set it to NULL.
    
    6) For the next 5 (!!) error conditions, *resp will contain garbage,
       and virNetlinkCommand() will goto it's cleanup code which will
       VIR_FREE(*resp), almost surely leading to a segfault.
    
    In addition to fixing these 6 problems, this patch also makes the
    following two changes to make the function conform more closely to the
    style of other libvirt code:
    
    1) Change the handling of return code from "named rc and defaulted to
    0, but changed to -1 on error" to the more common "named ret and
    defaulted to -1, but changed to 0 on success".
    
    2) Rename the "error" label to "cleanup", since the code that follows
    is executed in success cases as well as failure.
    5d85b8a8
virnetlink.c 23.1 KB