[libvirt] [PATCH v3] nwfilter: Don't leak @inetaddr
John Ferlan
jferlan at redhat.com
Wed Sep 27 14:02:40 UTC 2017
On 09/27/2017 09:34 AM, Erik Skultety wrote:
> On Wed, Sep 27, 2017 at 08:06:42AM -0400, John Ferlan wrote:
>>
>> $subj:
>>
>> nwfilter: Fix memory leak in learnIPAddressThread
>>
>> On 09/26/2017 09:01 PM, ZhiPeng Lu wrote:
>>> In learnIPAddressThread()the @inetaddr may be leaked.
>>>
>>
>> Changing this to:
>>
>> Don't leak @inetaddr within the done: processing when attempting
>> to instantiate the filter.
>>
>>
>>> Signed-off-by: ZhiPeng Lu <lu.zhipeng at zte.com.cn>
>>> ---
>>> src/nwfilter/nwfilter_learnipaddr.c | 6 +++++-
>>> 1 file changed, 5 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/src/nwfilter/nwfilter_learnipaddr.c b/src/nwfilter/nwfilter_learnipaddr.c
>>> index cfd92d9..0cadf73 100644
>>> --- a/src/nwfilter/nwfilter_learnipaddr.c
>>> +++ b/src/nwfilter/nwfilter_learnipaddr.c
>>> @@ -605,6 +605,7 @@ learnIPAddressThread(void *arg)
>>>
>>> if (req->status == 0) {
>>> int ret;
>>> + int mapipret = -1;
>>> virSocketAddr sa;
>>> sa.len = sizeof(sa.data.inet4);
>>> sa.data.inet4.sin_family = AF_INET;
>>> @@ -622,7 +623,7 @@ learnIPAddressThread(void *arg)
>>> virNWFilterUnlockIface(req->ifname);
>>>
>>> if ((inetaddr = virSocketAddrFormat(&sa)) != NULL) {
>>> - if (virNWFilterIPAddrMapAddIPAddr(req->ifname, inetaddr) < 0) {
>>> + if ((mapipret = virNWFilterIPAddrMapAddIPAddr(req->ifname, inetaddr)) < 0) {
>>> VIR_ERROR(_("Failed to add IP address %s to IP address "
>>> "cache for interface %s"), inetaddr, req->ifname);
>>> }
>>> @@ -637,6 +638,9 @@ learnIPAddressThread(void *arg)
>>> req->filterparams);
>>> VIR_DEBUG("Result from applying firewall rules on "
>>> "%s with IP addr %s : %d", req->ifname, inetaddr, ret);
>>> + if (mapipret < 0)
>>> + VIR_FREE(inetaddr);
>>> +
>>
>> What's the purpose of mapipret? @inetaddr isn't allocated because of
>> the return of virNWFilterIPAddrMapAddIPAddr it's allocated because of
>> virSocketAddrFormat and thus would need to be VIR_FREE'd regardless.
>>
>> I've fixed that by just removing the unnecessary @mapipret and just
>> using VIR_FREE() at the end of the if statement.
>
> That's a wrong fix, because as ZhiPeng Lu noted in previous version, you freed
> something that is assigned to the ipAddressMap pool on success, so the next
> time you access it, you'll get a SIGSEGV
>
Ugh! My brain couldn't parse what he wrote. I'm glad you could.
Still this pile of code is awful....
virNWFilterIPAddrMapAddIPAddr takes @addr and if not found in
ipAddressMap->hashTable, it creates a @val from @addr and inserts @val
into a hash table and the caller can/should free @addr on success.
If it is found, then virNWFilterVarValueAddValue is called and on
success, yes, it consumes @addr and caller shouldn't free @addr
So how is the caller to know that @addr has been consumed or not on
success. For one instance it is, but on the other it isn't. Certainly
on failure it's not consumed and free-able.
> Erik
>
> Btw I wanted to respond to the previous version in the morning, but I couldn't
> come up with anything else than either using STRDUP in
> virNWFilterIPAddrMapAddIPAddr, so then we could go with the proposal you just
> pushed, or we could refactor the whole nwfilter as it's a real mess...(that's a
> joke btw, I don't think anyone is volunteering to that any time soon) - it's a
> shame that the nwfilter code is kinda "no touchy" unless something crashes.
>
So I think the fix to this awful code would be to use VIR_STRDUP() in
virNWFilterIPAddrMapAddIPAddr for the else condition into a @tmp
variable that would be used in call to virNWFilterVarValueAddValue. I'll
send something shortly.
John
More information about the libvir-list
mailing list