From ed06fade6dc46df0a38caab2e465dfaabfc76f46 Mon Sep 17 00:00:00 2001 From: Peter Wagner Date: Wed, 20 Feb 2019 10:59:50 -0500 Subject: [PATCH] nfs-utils: fix addrinfo usage with musl-1.1.21 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 The free in support/export/hostname.c is removed too See: https://www.openwall.com/lists/musl/2019/02/17/2 Define and use wrapper function nfs_freeaddrinfo to handle freeaddrinfo versions that don't tolerate NULL pointers Reviewed-by: Chuck Lever Signed-off-by: Peter Wagner Signed-off-by: Steve Dickson --- support/export/client.c | 6 +++--- support/export/hostname.c | 4 ++-- support/include/nfslib.h | 11 +++++++++++ support/nfs/getport.c | 7 ++++--- support/nfs/svc_create.c | 6 +++--- support/nfsidmap/umich_ldap.c | 3 ++- tests/nsm_client/nsm_client.c | 2 +- utils/exportfs/exportfs.c | 10 +++++----- utils/gssd/gssd.c | 4 ++-- utils/gssd/krb5_util.c | 3 ++- utils/mount/network.c | 6 +++--- utils/mount/stropts.c | 3 ++- utils/mountd/auth.c | 2 +- utils/mountd/cache.c | 10 +++++----- utils/mountd/mountd.c | 4 ++-- utils/mountd/rmtab.c | 2 +- utils/nfsd/nfssvc.c | 3 +-- utils/statd/hostname.c | 11 ++++++----- utils/statd/sm-notify.c | 14 +++++++------- 19 files changed, 63 insertions(+), 48 deletions(-) diff --git a/support/export/client.c b/support/export/client.c index baf59c8..a1fba01 100644 --- a/support/export/client.c +++ b/support/export/client.c @@ -210,7 +210,7 @@ init_subnetwork(nfs_client *clp) set_addrlist(clp, 0, ai->ai_addr); family = ai->ai_addr->sa_family; - freeaddrinfo(ai); + nfs_freeaddrinfo(ai); switch (family) { case AF_INET: @@ -309,7 +309,7 @@ client_lookup(char *hname, int canonical) init_addrlist(clp, ai); out: - freeaddrinfo(ai); + nfs_freeaddrinfo(ai); return clp; } @@ -674,7 +674,7 @@ check_netgroup(const nfs_client *clp, const struct addrinfo *ai) tmp = host_pton(hname); if (tmp != NULL) { char *cname = host_canonname(tmp->ai_addr); - freeaddrinfo(tmp); + nfs_freeaddrinfo(tmp); /* The resulting FQDN may be in our netgroup. */ if (cname != NULL) { diff --git a/support/export/hostname.c b/support/export/hostname.c index 96c5449..be4d7f6 100644 --- a/support/export/hostname.c +++ b/support/export/hostname.c @@ -130,7 +130,7 @@ host_pton(const char *paddr) if (!inet4 && ai->ai_addr->sa_family == AF_INET) { xlog(D_GENERAL, "%s: failed to convert %s", __func__, paddr); - freeaddrinfo(ai); + nfs_freeaddrinfo(ai); break; } return ai; @@ -292,7 +292,7 @@ host_reliable_addrinfo(const struct sockaddr *sap) if (nfs_compare_sockaddr(a->ai_addr, sap)) break; - freeaddrinfo(ai); + nfs_freeaddrinfo(ai); ai = NULL; if (!a) goto out; diff --git a/support/include/nfslib.h b/support/include/nfslib.h index ab8b2bf..b09fce4 100644 --- a/support/include/nfslib.h +++ b/support/include/nfslib.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -156,4 +157,14 @@ void libtirpc_set_debug(char *name, int level, int use_stderr); #define UNUSED(x) UNUSED_ ## x __attribute__((unused)) +/* + * 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); + } +} #endif /* NFSLIB_H */ diff --git a/support/nfs/getport.c b/support/nfs/getport.c index 081594c..e458d8f 100644 --- a/support/nfs/getport.c +++ b/support/nfs/getport.c @@ -47,6 +47,7 @@ #include "sockaddr.h" #include "nfsrpc.h" +#include "nfslib.h" /* * Try a local socket first to access the local rpcbind daemon @@ -109,7 +110,7 @@ static int nfs_gp_loopback_address(struct sockaddr *sap, socklen_t *salen) ret = 1; } - freeaddrinfo(gai_results); + nfs_freeaddrinfo(gai_results); return ret; } @@ -134,8 +135,8 @@ static in_port_t nfs_gp_getservbyname(const char *service, sin = (const struct sockaddr_in *)gai_results->ai_addr; port = sin->sin_port; - - freeaddrinfo(gai_results); + + nfs_freeaddrinfo(gai_results); return port; } diff --git a/support/nfs/svc_create.c b/support/nfs/svc_create.c index ef7ff05..4e14430 100644 --- a/support/nfs/svc_create.c +++ b/support/nfs/svc_create.c @@ -273,7 +273,7 @@ svc_create_nconf_rand_port(const char *name, const rpcprog_t program, bindaddr.qlen = SOMAXCONN; xprt = svc_tli_create(RPC_ANYFD, nconf, &bindaddr, 0, 0); - freeaddrinfo(ai); + nfs_freeaddrinfo(ai); if (xprt == NULL) { xlog(L_ERROR, "Failed to create listener xprt " "(%s, %u, %s)", name, version, nconf->nc_netid); @@ -364,11 +364,11 @@ svc_create_nconf_fixed_port(const char *name, const rpcprog_t program, svc_create_cache_xprt(xprt); - freeaddrinfo(ai); + nfs_freeaddrinfo(ai); return 1; out_free: - freeaddrinfo(ai); + nfs_freeaddrinfo(ai); return 0; } diff --git a/support/nfsidmap/umich_ldap.c b/support/nfsidmap/umich_ldap.c index b661110..10d1d97 100644 --- a/support/nfsidmap/umich_ldap.c +++ b/support/nfsidmap/umich_ldap.c @@ -46,6 +46,7 @@ /* We are using deprecated functions, get the prototypes... */ #define LDAP_DEPRECATED 1 #include +#include "nfslib.h" #include "nfsidmap.h" #include "nfsidmap_plugin.h" #include "nfsidmap_private.h" @@ -1089,7 +1090,7 @@ get_canonical_hostname(const char *inname) return_name = strdup (tmphost); out_free: - freeaddrinfo(ap); + nfs_freeaddrinfo(ap); out_err: return return_name; } diff --git a/tests/nsm_client/nsm_client.c b/tests/nsm_client/nsm_client.c index 0fa3422..8dc0591 100644 --- a/tests/nsm_client/nsm_client.c +++ b/tests/nsm_client/nsm_client.c @@ -243,7 +243,7 @@ nsm_client_get_rpcclient(const char *node) printf("RPC client creation failed\n"); } out: - freeaddrinfo(ai); + nfs_freeaddrinfo(ai); return client; } diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c index cd3c979..333eadc 100644 --- a/utils/exportfs/exportfs.c +++ b/utils/exportfs/exportfs.c @@ -282,7 +282,7 @@ exportfs_parsed(char *hname, char *path, char *options, int verbose) validate_export(exp); out: - freeaddrinfo(ai); + nfs_freeaddrinfo(ai); } static int exportfs_generic(char *arg, char *options, int verbose) @@ -395,7 +395,7 @@ unexportfs_parsed(char *hname, char *path, int verbose) if (!success) xlog(L_ERROR, "Could not find '%s:%s' to unexport.", hname, path); - freeaddrinfo(ai); + nfs_freeaddrinfo(ai); } static int unexportfs_generic(char *arg, int verbose) @@ -588,7 +588,7 @@ address_list(const char *hostname) if (ai != NULL) { /* @hostname was a presentation address */ cname = host_canonname(ai->ai_addr); - freeaddrinfo(ai); + nfs_freeaddrinfo(ai); if (cname != NULL) goto out; } @@ -639,8 +639,8 @@ matchhostname(const char *hostname1, const char *hostname2) } out: - freeaddrinfo(results1); - freeaddrinfo(results2); + nfs_freeaddrinfo(results1); + nfs_freeaddrinfo(results2); return result; } diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c index 2e92f28..7eeb05f 100644 --- a/utils/gssd/gssd.c +++ b/utils/gssd/gssd.c @@ -172,14 +172,14 @@ gssd_addrstr_to_sockaddr(struct sockaddr *sa, const char *node, const char *port if (sin6->sin6_scope_id) { printerr(0, "ERROR: address %s has non-zero " "sin6_scope_id!\n", node); - freeaddrinfo(res); + nfs_freeaddrinfo(res); return false; } } #endif /* IPV6_SUPPORTED */ memcpy(sa, res->ai_addr, res->ai_addrlen); - freeaddrinfo(res); + nfs_freeaddrinfo(res); return true; } diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c index eba1aac..6daba44 100644 --- a/utils/gssd/krb5_util.c +++ b/utils/gssd/krb5_util.c @@ -121,6 +121,7 @@ #include #include +#include "nfslib.h" #include "gssd.h" #include "err_util.h" #include "gss_util.h" @@ -587,7 +588,7 @@ get_full_hostname(const char *inhost, char *outhost, int outhostlen) goto out; } strncpy(outhost, addrs->ai_canonname, outhostlen); - freeaddrinfo(addrs); + nfs_freeaddrinfo(addrs); for (c = outhost; *c != '\0'; c++) *c = tolower(*c); diff --git a/utils/mount/network.c b/utils/mount/network.c index 356f663..fc21110 100644 --- a/utils/mount/network.c +++ b/utils/mount/network.c @@ -250,7 +250,7 @@ int nfs_lookup(const char *hostname, const sa_family_t family, break; } - freeaddrinfo(gai_results); + nfs_freeaddrinfo(gai_results); return ret; } @@ -307,7 +307,7 @@ int nfs_string_to_sockaddr(const char *address, struct sockaddr *sap, } break; } - freeaddrinfo(gai_results); + nfs_freeaddrinfo(gai_results); } return ret; @@ -1180,7 +1180,7 @@ static int nfs_ca_gai(const struct sockaddr *sap, *buflen = gai_results->ai_addrlen; memcpy(buf, gai_results->ai_addr, *buflen); - freeaddrinfo(gai_results); + nfs_freeaddrinfo(gai_results); return 1; } diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c index 0a25b1f..a093926 100644 --- a/utils/mount/stropts.c +++ b/utils/mount/stropts.c @@ -35,6 +35,7 @@ #include #include +#include "nfslib.h" #include "sockaddr.h" #include "xcommon.h" #include "mount.h" @@ -1268,7 +1269,7 @@ int nfsmount_string(const char *spec, const char *node, char *type, } else nfs_error(_("%s: internal option parsing error"), progname); - freeaddrinfo(mi.address); + nfs_freeaddrinfo(mi.address); free(mi.hostname); return retval; } diff --git a/utils/mountd/auth.c b/utils/mountd/auth.c index cb4848c..67627f7 100644 --- a/utils/mountd/auth.c +++ b/utils/mountd/auth.c @@ -297,7 +297,7 @@ auth_authenticate(const char *what, const struct sockaddr *caller, what, buf, nfs_get_port(caller), path, epath, error); } - freeaddrinfo(ai); + nfs_freeaddrinfo(ai); return exp; } diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c index 7e8d403..2cb370f 100644 --- a/utils/mountd/cache.c +++ b/utils/mountd/cache.c @@ -113,7 +113,7 @@ static void auth_unix_ip(int f) ai = client_resolve(tmp->ai_addr); if (ai) { client = client_compose(ai); - freeaddrinfo(ai); + nfs_freeaddrinfo(ai); } } bp = buf; blen = sizeof(buf); @@ -133,7 +133,7 @@ static void auth_unix_ip(int f) xlog(D_CALL, "auth_unix_ip: client %p '%s'", client, client?client: "DEFAULT"); free(client); - freeaddrinfo(tmp); + nfs_freeaddrinfo(tmp); } @@ -667,7 +667,7 @@ static struct addrinfo *lookup_client_addr(char *dom) if (tmp == NULL) return NULL; ret = client_resolve(tmp->ai_addr); - freeaddrinfo(tmp); + nfs_freeaddrinfo(tmp); return ret; } @@ -834,7 +834,7 @@ static void nfsd_fh(int f) out: if (found_path) free(found_path); - freeaddrinfo(ai); + nfs_freeaddrinfo(ai); free(dom); xlog(D_CALL, "nfsd_fh: found %p path %s", found, found ? found->e_path : NULL); } @@ -1355,7 +1355,7 @@ 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); + nfs_freeaddrinfo(ai); } diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c index 086c39b..fb7bba4 100644 --- a/utils/mountd/mountd.c +++ b/utils/mountd/mountd.c @@ -578,10 +578,10 @@ static void prune_clients(nfs_export *exp, struct exportnode *e) *cp = c->gr_next; xfree(c->gr_name); xfree(c); - freeaddrinfo(ai); + nfs_freeaddrinfo(ai); continue; } - freeaddrinfo(ai); + nfs_freeaddrinfo(ai); } cp = &(c->gr_next); } diff --git a/utils/mountd/rmtab.c b/utils/mountd/rmtab.c index 3ae0dbb..c896243 100644 --- a/utils/mountd/rmtab.c +++ b/utils/mountd/rmtab.c @@ -226,7 +226,7 @@ mountlist_list(void) ai = host_pton(rep->r_client); if (ai != NULL) { m->ml_hostname = host_canonname(ai->ai_addr); - freeaddrinfo(ai); + nfs_freeaddrinfo(ai); } } if (m->ml_hostname == NULL) diff --git a/utils/nfsd/nfssvc.c b/utils/nfsd/nfssvc.c index 1e6ffd6..720bdd9 100644 --- a/utils/nfsd/nfssvc.c +++ b/utils/nfsd/nfssvc.c @@ -246,8 +246,7 @@ error: close(fd); if (sockfd >= 0) close(sockfd); - if (addrhead) - freeaddrinfo(addrhead); + nfs_freeaddrinfo(addrhead); return (bounded ? 0 : rc); } diff --git a/utils/statd/hostname.c b/utils/statd/hostname.c index 8cccdb8..16e21fc 100644 --- a/utils/statd/hostname.c +++ b/utils/statd/hostname.c @@ -35,6 +35,7 @@ #include #include +#include "nfslib.h" #include "sockaddr.h" #include "statd.h" #include "xlog.h" @@ -203,7 +204,7 @@ statd_canonical_name(const char *hostname) _Bool result; result = get_nameinfo(ai->ai_addr, ai->ai_addrlen, buf, (socklen_t)sizeof(buf)); - freeaddrinfo(ai); + nfs_freeaddrinfo(ai); if (!result || buf[0] == '\0') /* OK to use presentation address, * if no reverse map exists */ @@ -217,7 +218,7 @@ statd_canonical_name(const char *hostname) if (ai == NULL) return NULL; strcpy(buf, ai->ai_canonname); - freeaddrinfo(ai); + nfs_freeaddrinfo(ai); return strdup(buf); } @@ -253,7 +254,7 @@ statd_canonical_list(const char *hostname) _Bool result; result = get_nameinfo(ai->ai_addr, ai->ai_addrlen, buf, (socklen_t)sizeof(buf)); - freeaddrinfo(ai); + nfs_freeaddrinfo(ai); if (result) goto out; } @@ -308,8 +309,8 @@ statd_matchhostname(const char *hostname1, const char *hostname2) } out: - freeaddrinfo(results2); - freeaddrinfo(results1); + nfs_freeaddrinfo(results2); + nfs_freeaddrinfo(results1); xlog(D_CALL, "%s: hostnames %s and %s %s", __func__, hostname1, hostname2, diff --git a/utils/statd/sm-notify.c b/utils/statd/sm-notify.c index 29dad38..5e394a3 100644 --- a/utils/statd/sm-notify.c +++ b/utils/statd/sm-notify.c @@ -36,6 +36,7 @@ #include "sockaddr.h" #include "xlog.h" #include "nsm.h" +#include "nfslib.h" #include "nfsrpc.h" /* glibc before 2.3.4 */ @@ -179,7 +180,7 @@ smn_verify_my_name(const char *name) case 0: /* @name was a presentation address */ retval = smn_get_hostname(ai->ai_addr, ai->ai_addrlen, name); - freeaddrinfo(ai); + nfs_freeaddrinfo(ai); if (retval == NULL) return NULL; break; @@ -253,8 +254,7 @@ static void smn_forget_host(struct nsm_host *host) free((void *)host->my_name); free((void *)host->mon_name); free(host->name); - if (host->ai) - freeaddrinfo(host->ai); + nfs_freeaddrinfo(host->ai); free(host); } @@ -430,7 +430,7 @@ retry: if (srcport) { if (bind(sock, ai->ai_addr, ai->ai_addrlen) == -1) { xlog(L_ERROR, "Failed to bind RPC socket: %m"); - freeaddrinfo(ai); + nfs_freeaddrinfo(ai); (void)close(sock); return -1; } @@ -440,7 +440,7 @@ retry: if (smn_bindresvport(sock, ai->ai_addr) == -1) { xlog(L_ERROR, "bindresvport on RPC socket failed: %m"); - freeaddrinfo(ai); + nfs_freeaddrinfo(ai); (void)close(sock); return -1; } @@ -449,13 +449,13 @@ retry: se = getservbyport((int)nfs_get_port(ai->ai_addr), "udp"); if (se != NULL && retry_cnt < 100) { retry_cnt++; - freeaddrinfo(ai); + nfs_freeaddrinfo(ai); (void)close(sock); goto retry; } } - freeaddrinfo(ai); + nfs_freeaddrinfo(ai); return sock; } -- 1.8.3.1