Re: [PATCH] nfs-utils: fix addrinfo usage with musl-1.1.21

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On 2/17/19 9:21 PM, Chuck Lever wrote:
> 
> 
>> On Feb 17, 2019, at 6:11 PM, Peter Wagner <tripolar@xxxxxx> wrote:
>>
>> Hi Chuck,
>>
>>> It might be cleaner to define a local version of freeaddrinfo in
>>> nfs-utils to reduce duplication of code and provide a place
>>> in the code itself to document this issue with a comment.
>>
>> But why use a local freeaddrinfo function? The code is checking at
>> multiple places if an addrinfo* == NULL and if it's NULL it just returns
>> without freeing it and at some other places it just frees it. For 
>> censistence reasions i would propose to check if it's != NULL before 
>> freeing it.
> 
> I didn't think this would be a controversial suggestion.
> Here is what I meant:
> 
> Find a common location, say support/include/exportfs.h, and
> add this:
> 
> /*
>  * Some versions of freeaddrinfo(3) do not tolerate being
>  * passed a NULL pointer.
>  */
> static inline void nfs_freeaddrinfo(struct addrinfo *ai)
> {
> 	if (ai)
> 		freeaddrinfo(ai);
> }
> 
> Then replace the freeaddrinfo() call sites within nfs-utils
> with calls to nfs_freeaddrinfo().
+1

> 
> 
> 
> The logic in host_numeric_addrinfo() will need a closer
> look. If what Rich says is true then both freeing the
> ai_canonname string _and_ replacing it with strdup(3)
> will be problematic.
> 
> I see that host_reliable_addrinfo() has the same issue.
I just ran Rich's program that is suppose to
crash... It does not crash on Fedora 29.

> 
> 
>> The spec also just defines the != NULL case and we shouldn't depend on
>> undefined behavior imho.
> 
> Some counterpoints:
> 
> - It is good defensive coding that a library function should
> perform basic sanity checks on its argument(s) to prevent
> crashes.
> 
> - It's always possible for a spec to be wrong.
> 
> - If a spec says the behavior is "undefined" that generally
> means the spec writer is giving the implementer permission
> to choose a convenient and possibly useful behavior. Crashing
> is not especially useful. A better approach would be to ignore
> NULL, and add hooks to a tool like valgrind to report this
> kind of issue.
> 
> - nfs-utils is not careless about this. The design of the code
> clearly assumes that freeaddrinfo(3) will not crash in this
> case. It's not an unreasonable assumption. The goal here is
> to construct simple-to-read code.
> 
> - Strictly speaking, d1395c43 introduced a regression in
> freeaddrinfo(3) that should be fixed, because existing
> applications have depended on the old behavior for a long
> while. IMO a better fix here would be to make musl's
> freeaddrinfo(3) deal properly with a NULL argument instead
> of changing all of its callers, but that's not my call.I also took a look at how freeaddrinfo(3) in glibc works:

void
freeaddrinfo (struct addrinfo *ai)
{
  struct addrinfo *p;

  while (ai != NULL)
    {
      p = ai;
      ai = ai->ai_next;
      free (p->ai_canonname);
      free (p);
    }
}
It makes the assumption that ai_canonname is
free-able memory.... 

steved.
> 
> - The equivalent to free(3) in the Linux kernel, kfree(),
> explicitly allows callers to pass NULL because that eliminates
> the need to add "if (arg != NULL)" at every call site.
> 
> I'm not arguing that we should do nothing, but rather that
> there is a matter of subjectivity and taste here about what
> is correct behavior. The OG spec is just one opinion.
> 
> 
>> Regards,
>> Peter
>>
>>
>>
>> On Sun, 17 Feb 2019 12:40:10 -0500
>> Chuck Lever <chuck.lever@xxxxxxxxxx> wrote:
>>
>>> Hi Peter-
>>>
>>>> On Feb 17, 2019, at 11:39 AM, Peter Wagner <tripolar@xxxxxx> wrote:
>>>>
>>>> Afer the update to musl 1.1.21 freeaddrinfo is broken in some
>>>> places in the nfs-utils code because glibc seems to ignore when
>>>> freeaddrinfo is called with a NULL pointer which seems to be not
>>>> defined in the spec.
>>>>
>>>> See: https://www.openwall.com/lists/musl/2019/02/03/4  
>>>
>>> It might be cleaner to define a local version of freeaddrinfo in
>>> nfs-utils to reduce duplication of code and provide a place
>>> in the code itself to document this issue with a comment.
>>>
>>>
>>>> The free in support/export/hostname.c is removed too
>>>>
>>>> See: https://www.openwall.com/lists/musl/2019/02/17/2  
>>>
>>> Actually this seems like a separate issue because a distribution
>>> that uses another C library might decide it is pertinent to apply
>>> separately from the other changes here.
>>>
>>> Please create a separate patch. It should remove the free(3)
>>> call instead of commenting it out, and the patch description
>>> should have its own copy of Rich’s email comments.
>>>
>>> Thanks!
>>>
>>>
>>>> From 43e27735553b4c1e75964f32b2f887e84398055f Mon Sep 17 00:00:00
>>>> 2001 From: Peter Wagner <tripolar@xxxxxx>
>>>> Date: Sun, 17 Feb 2019 17:32:08 +0100
>>>> Subject: [PATCH] fix addrinfo usage
>>>>
>>>> Signed-off-by: Peter Wagner <tripolar@xxxxxx>
>>>> ---
>>>> support/export/client.c   |  3 ++-
>>>> support/export/hostname.c |  2 +-
>>>> utils/exportfs/exportfs.c | 12 ++++++++----
>>>> utils/mount/stropts.c     |  3 ++-
>>>> utils/mountd/cache.c      |  6 ++++--
>>>> utils/statd/hostname.c    |  6 ++++--
>>>> 6 files changed, 21 insertions(+), 11 deletions(-)
>>>>
>>>> diff --git a/support/export/client.c b/support/export/client.c
>>>> index baf59c8..750eb7d 100644
>>>> --- a/support/export/client.c
>>>> +++ b/support/export/client.c
>>>> @@ -309,7 +309,8 @@ client_lookup(char *hname, int canonical)
>>>>      init_addrlist(clp, ai);
>>>>
>>>> out:
>>>> -    freeaddrinfo(ai);
>>>> +    if (ai)
>>>> +        freeaddrinfo(ai);
>>>>  return clp;
>>>> }
>>>>
>>>> diff --git a/support/export/hostname.c b/support/export/hostname.c
>>>> index 5c4c824..710bf61 100644
>>>> --- a/support/export/hostname.c
>>>> +++ b/support/export/hostname.c
>>>> @@ -354,7 +354,7 @@ host_numeric_addrinfo(const struct sockaddr
>>>> *sap)
>>>>   * getaddrinfo(AI_NUMERICHOST) never fills in ai_canonname
>>>>   */
>>>>  if (ai != NULL) {
>>>> -        free(ai->ai_canonname);        /* just in case */
>>>> +        //free(ai->ai_canonname);        /* just in case */
>>>>      ai->ai_canonname = strdup(buf);
>>>>      if (ai->ai_canonname == NULL) {
>>>>          freeaddrinfo(ai);
>>>> diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c
>>>> index cd3c979..2f8d59a 100644
>>>> --- a/utils/exportfs/exportfs.c
>>>> +++ b/utils/exportfs/exportfs.c
>>>> @@ -282,7 +282,8 @@ exportfs_parsed(char *hname, char *path, char
>>>> *options, int verbose) validate_export(exp);
>>>>
>>>> out:
>>>> -    freeaddrinfo(ai);
>>>> +    if (ai)
>>>> +        freeaddrinfo(ai);
>>>> }
>>>>
>>>> static int exportfs_generic(char *arg, char *options, int verbose)
>>>> @@ -395,7 +396,8 @@ unexportfs_parsed(char *hname, char *path, int
>>>> verbose) if (!success)
>>>>      xlog(L_ERROR, "Could not find '%s:%s' to unexport.", hname,
>>>> path);
>>>>
>>>> -    freeaddrinfo(ai);
>>>> +    if (ai)
>>>> +        freeaddrinfo(ai);
>>>> }
>>>>
>>>> static int unexportfs_generic(char *arg, int verbose)
>>>> @@ -639,8 +641,10 @@ matchhostname(const char *hostname1, const
>>>> char *hostname2) }
>>>>
>>>> out:
>>>> -    freeaddrinfo(results1);
>>>> -    freeaddrinfo(results2);
>>>> +    if (results1)
>>>> +        freeaddrinfo(results1);
>>>> +    if (results2)
>>>> +        freeaddrinfo(results2);
>>>>  return result;
>>>> }
>>>>
>>>> diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
>>>> index 0a25b1f..8b7a0a8 100644
>>>> --- a/utils/mount/stropts.c
>>>> +++ b/utils/mount/stropts.c
>>>> @@ -1268,7 +1268,8 @@ int nfsmount_string(const char *spec, const
>>>> char *node, char *type, } else
>>>>      nfs_error(_("%s: internal option parsing error"), progname);
>>>>
>>>> -    freeaddrinfo(mi.address);
>>>> +    if (mi.address)
>>>> +        freeaddrinfo(mi.address);
>>>>  free(mi.hostname);
>>>>  return retval;
>>>> }
>>>> diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c
>>>> index 7e8d403..8cee1c8 100644
>>>> --- a/utils/mountd/cache.c
>>>> +++ b/utils/mountd/cache.c
>>>> @@ -834,7 +834,8 @@ static void nfsd_fh(int f)
>>>> out:
>>>>  if (found_path)
>>>>      free(found_path);
>>>> -    freeaddrinfo(ai);
>>>> +    if(ai)
>>>> +        freeaddrinfo(ai);
>>>>  free(dom);
>>>>  xlog(D_CALL, "nfsd_fh: found %p path %s", found, found ?
>>>> found->e_path : NULL); }
>>>> @@ -1355,7 +1356,8 @@ static void nfsd_export(int f)
>>>>  xlog(D_CALL, "nfsd_export: found %p path %s", found, path ?
>>>> path : NULL); if (dom) free(dom);
>>>>  if (path) free(path);
>>>> -    freeaddrinfo(ai);
>>>> +    if (ai)
>>>> +        freeaddrinfo(ai);
>>>> }
>>>>
>>>>
>>>> diff --git a/utils/statd/hostname.c b/utils/statd/hostname.c
>>>> index 8cccdb8..6556ab1 100644
>>>> --- a/utils/statd/hostname.c
>>>> +++ b/utils/statd/hostname.c
>>>> @@ -308,8 +308,10 @@ statd_matchhostname(const char *hostname1,
>>>> const char *hostname2) }
>>>>
>>>> out:
>>>> -    freeaddrinfo(results2);
>>>> -    freeaddrinfo(results1);
>>>> +    if (results2)
>>>> +        freeaddrinfo(results2);
>>>> +    if (results1)
>>>> +        freeaddrinfo(results1);
>>>>
>>>>  xlog(D_CALL, "%s: hostnames %s and %s %s", __func__,
>>>>          hostname1, hostname2,
>>>> -- 
>>>> 2.20.1
>>>>
>>>
>>
> 
> --
> Chuck Lever
> 
> 
> 



[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux