[Libguestfs] [libnbd PATCH 1/2] api: Avoid memory leak on certain strict_mode failures

Laszlo Ersek lersek at redhat.com
Tue Nov 30 16:09:40 UTC 2021


On 11/30/21 14:20, Eric Blake wrote:
> On Tue, Nov 30, 2021 at 01:08:24PM +0100, Laszlo Ersek wrote:
>> On 11/30/21 04:15, Eric Blake wrote:
>>> Commit e57681fa ("generator: Free closures on failure", v1.5.2) makes
>>> sure that once we copy a callback out of the caller's variable, then
>>> we ensure it is cleaned up on all error paths.  But I was developing
>>> two patch series in parallel, and due to botched rebasing on my part,
>>> shortly after, commit 76bc0f0b ("api: Add STRICT_BOUNDS/ZERO_SIZE to
>>> nbd_set_strict_mode", v1.5.3) accidentally re-introduced a return -1
>>> instead of a goto err on one of its two added error checks in the
>>> common handler, and that mistake was then copy-pasted into ba86bfd1
>>> ("api: Add STRICT_ALIGN to nbd_set_strict_mode", v1.5.3).
>>>
>>> As penance for reintroducing a leak so quickly back then, I'm now
>>> adding some testsuite coverage, which fails without the rw.c changes.
>>>
>>> Fixes: 76bc0f0b
>>> Fixes: ba86bfd1
>>> ---
>>>  lib/rw.c       |  4 ++--
>>>  tests/errors.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
>>>  2 files changed, 46 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/lib/rw.c b/lib/rw.c
>>> index cb25dbf..4ade750 100644
>>> --- a/lib/rw.c
>>> +++ b/lib/rw.c
>>> @@ -195,13 +195,13 @@ nbd_internal_command_common (struct nbd_handle *h,
>>>      if ((h->strict & LIBNBD_STRICT_BOUNDS) &&
>>>          (offset > h->exportsize || count > h->exportsize - offset)) {
>>>        set_error (count_err, "request out of bounds");
>>> -      return -1;
>>> +      goto err;
>>>      }
>>>
>>>      if (h->block_minimum && (h->strict & LIBNBD_STRICT_ALIGN) &&
>>>          (offset | count) & (h->block_minimum - 1)) {
>>>        set_error (EINVAL, "request is unaligned");
>>> -      return -1;
>>> +      goto err;
>>>      }
>>>    }
>>
>> One of those (rare) cases where I think that "ownership transfer on
>> error" is justified.
>>
>> Acked-by: Laszlo Ersek <lersek at redhat.com>
>>
>> (It would be nice though if "lib/internal.h" documented the
>> unconditional ownership transfer in nbd_internal_command_common().
> 
> It sort of does (in the function body, rather than as a contract at
> the declaration):
> https://gitlab.com/nbdkit/libnbd/-/blob/master/lib/rw.c#L283
> | err:
> |  /* Since we did not queue the command, we must free the callbacks. */
> 
>>
>> Or is that clear already from another part of the documentation, or a
>> header file?)
> 
> It is also in the documentation:
> https://gitlab.com/nbdkit/libnbd/-/blob/master/docs/libnbd.pod#L815
> |=head2 Callback lifetimes
> |
> |You can associate an optional free function with callbacks.  Libnbd
> |will call this function when the callback will not be called again by
> |libnbd, including in the case where the API fails.

Perfect!

> 
> So I've pushed this one as commit 76f4d5af5c1c, with a bit more
> verbosity in the commit message.
> 
> I'll backport it to stable branches and probably cut a minor release
> later today, once I have the python leak fixed as well.
> 

Thanks!
Laszlo




More information about the Libguestfs mailing list