diff --git a/0001-Fix-regression-introduced-by-change-rpc-version-orde.patch b/0001-Fix-regression-introduced-by-change-rpc-version-orde.patch new file mode 100644 index 0000000..7b2795b --- /dev/null +++ b/0001-Fix-regression-introduced-by-change-rpc-version-orde.patch @@ -0,0 +1,73 @@ +From 25d38d744997d5ff03d8b0f2cdd79c0fb7185cca Mon Sep 17 00:00:00 2001 +From: Thomas Blume +Date: Wed, 18 Apr 2018 08:44:49 -0400 +Subject: [PATCH] Fix regression introduced by change rpc version order patch + +Fix a socket leak introduced by commit 5e7b57bc20bd9cadff +(rpcinfo: change order of version to be tried to 4, 3, 2) +The new function __try_protocol_version_2 doesn't return +the client, so it can't be closed via CLNT_DESTROY in the +calling function. + +Signed-off-by: Thomas Blume +Signed-off-by: Steve Dickson +--- + src/rpcb_clnt.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/src/rpcb_clnt.c b/src/rpcb_clnt.c +index a94fc73..4b44364 100644 +--- a/src/rpcb_clnt.c ++++ b/src/rpcb_clnt.c +@@ -752,7 +752,7 @@ __try_protocol_version_2(program, version, nconf, host, tp) + + client = getpmaphandle(nconf, host, &parms.r_addr); + if (client == NULL) +- return (NULL); ++ goto error; + + /* + * Set retry timeout. +@@ -771,11 +771,11 @@ __try_protocol_version_2(program, version, nconf, host, tp) + if (clnt_st != RPC_SUCCESS) { + rpc_createerr.cf_stat = RPC_PMAPFAILURE; + clnt_geterr(client, &rpc_createerr.cf_error); +- return (NULL); ++ goto error; + } else if (port == 0) { + pmapaddress = NULL; + rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; +- return (NULL); ++ goto error; + } + port = htons(port); + CLNT_CONTROL(client, CLGET_SVC_ADDR, (char *)&remote); +@@ -789,14 +789,24 @@ __try_protocol_version_2(program, version, nconf, host, tp) + free(pmapaddress); + pmapaddress = NULL; + } +- return (NULL); ++ goto error; + } + memcpy(pmapaddress->buf, remote.buf, remote.len); + memcpy(&((char *)pmapaddress->buf)[sizeof (short)], + (char *)(void *)&port, sizeof (short)); + pmapaddress->len = pmapaddress->maxlen = remote.len; + ++ CLNT_DESTROY(client); + return pmapaddress; ++ ++error: ++ if (client) { ++ CLNT_DESTROY(client); ++ client = NULL; ++ ++ } ++ return (NULL); ++ + } + #endif + +-- +2.13.6 + diff --git a/002-revert-binddynport.patch b/002-revert-binddynport.patch new file mode 100644 index 0000000..ffec408 --- /dev/null +++ b/002-revert-binddynport.patch @@ -0,0 +1,256 @@ +diff --git a/src/Makefile.am b/src/Makefile.am +index 932414d..fba2aa4 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -15,9 +15,8 @@ lib_LTLIBRARIES = libtirpc.la + libtirpc_la_LDFLAGS = @LDFLAG_NOUNDEFINED@ -no-undefined -lpthread + libtirpc_la_LDFLAGS += -version-info @LT_VERSION_INFO@ + +-libtirpc_la_SOURCES = auth_none.c auth_unix.c authunix_prot.c \ +- binddynport.c bindresvport.c \ +- clnt_bcast.c clnt_dg.c clnt_generic.c clnt_perror.c clnt_raw.c clnt_simple.c \ ++libtirpc_la_SOURCES = auth_none.c auth_unix.c authunix_prot.c bindresvport.c clnt_bcast.c \ ++ clnt_dg.c clnt_generic.c clnt_perror.c clnt_raw.c clnt_simple.c \ + clnt_vc.c rpc_dtablesize.c getnetconfig.c getnetpath.c getrpcent.c \ + getrpcport.c mt_misc.c pmap_clnt.c pmap_getmaps.c pmap_getport.c \ + pmap_prot.c pmap_prot2.c pmap_rmt.c rpc_prot.c rpc_commondata.c \ +diff --git a/src/binddynport.c b/src/binddynport.c +deleted file mode 100644 +index 062629a..0000000 +--- a/src/binddynport.c ++++ /dev/null +@@ -1,139 +0,0 @@ +-/* +- * Copyright (c) 2018, Oracle America, Inc. +- * All rights reserved. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * - Redistributions of source code must retain the above copyright notice, +- * this list of conditions and the following disclaimer. +- * - Redistributions in binary form must reproduce the above copyright notice, +- * this list of conditions and the following disclaimer in the documentation +- * and/or other materials provided with the distribution. +- * - Neither the name of "Oracle America, Inc." nor the names of its +- * contributors may be used to endorse or promote products derived +- * from this software without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +- * POSSIBILITY OF SUCH DAMAGE. +- */ +- +-#include +-#include +-#include +- +-#include +-#include +- +-#include +-#include +-#include +-#include +- +-#include +- +-#include "reentrant.h" +-#include "rpc_com.h" +- +-extern pthread_mutex_t port_lock; +- +-/* +- * Dynamic port range as defined in RFC 6335 Section 6. +- * This range avoids all IANA-assigned service port +- * numbers. +- */ +-enum { +- LOWPORT = 49152, +- ENDPORT = 65534, +- NPORTS = ENDPORT - LOWPORT + 1, +-}; +- +-/* +- * Bind a socket to a dynamically-assigned IP port. +- * +- * @fd is an open but unbound socket. +- * +- * On each call, a port number is chosen at random from +- * within the dynamic/private port range, even if the +- * caller has CAP_NET_ADMIN_BIND. +- * +- * Returns 0 on success, -1 on failure. errno may be +- * set to a non-determinant value. +- * +- * This function is re-entrant. +- */ +-int __binddynport(int fd) +-{ +- struct sockaddr_storage ss; +-#ifdef INET6 +- struct sockaddr_in6 *sin6; +-#endif +- struct sockaddr_in *sin; +- static unsigned int seed; +- in_port_t port, *portp; +- struct sockaddr *sap; +- socklen_t salen; +- int i, res; +- +- if (__rpc_sockisbound(fd)) +- return 0; +- +- res = -1; +- sap = (struct sockaddr *)(void *)&ss; +- salen = sizeof(ss); +- memset(sap, 0, salen); +- +- mutex_lock(&port_lock); +- +- if (getsockname(fd, sap, &salen) == -1) +- goto out; +- +- switch (ss.ss_family) { +- case AF_INET: +- sin = (struct sockaddr_in *)(void *)&ss; +- portp = &sin->sin_port; +- salen = sizeof(struct sockaddr_in); +- break; +-#ifdef INET6 +- case AF_INET6: +- sin6 = (struct sockaddr_in6 *)(void *)&ss; +- portp = &sin6->sin6_port; +- salen = sizeof(struct sockaddr_in6); +- break; +-#endif +- default: +- goto out; +- } +- +- if (!seed) { +- struct timeval tv; +- +- gettimeofday(&tv, NULL); +- seed = tv.tv_usec * getpid(); +- } +- port = (rand_r(&seed) % NPORTS) + LOWPORT; +- for (i = 0; i < NPORTS; ++i) { +- *portp = htons(port++); +- res = bind(fd, sap, salen); +- if (res >= 0) { +- res = 0; +- break; +- } +- if (errno != EADDRINUSE) +- break; +- if (port > ENDPORT) +- port = LOWPORT; +- } +- +-out: +- mutex_unlock(&port_lock); +- return res; +-} +diff --git a/src/clnt_generic.c b/src/clnt_generic.c +index e5a314f..3f3dabf 100644 +--- a/src/clnt_generic.c ++++ b/src/clnt_generic.c +@@ -47,7 +47,6 @@ + + extern bool_t __rpc_is_local_host(const char *); + int __rpc_raise_fd(int); +-extern int __binddynport(int fd); + + #ifndef NETIDLEN + #define NETIDLEN 32 +@@ -341,8 +340,7 @@ clnt_tli_create(int fd, const struct netconfig *nconf, + servtype = nconf->nc_semantics; + if (!__rpc_fd2sockinfo(fd, &si)) + goto err; +- if (__binddynport(fd) == -1) +- goto err; ++ bindresvport(fd, NULL); + } else { + if (!__rpc_fd2sockinfo(fd, &si)) + goto err; +diff --git a/src/rpc_soc.c b/src/rpc_soc.c +index af6c482..ed0892a 100644 +--- a/src/rpc_soc.c ++++ b/src/rpc_soc.c +@@ -67,8 +67,6 @@ + + extern mutex_t rpcsoc_lock; + +-extern int __binddynport(int fd); +- + static CLIENT *clnt_com_create(struct sockaddr_in *, rpcprog_t, rpcvers_t, + int *, u_int, u_int, char *, int); + static SVCXPRT *svc_com_create(int, u_int, u_int, char *); +@@ -147,8 +145,7 @@ clnt_com_create(raddr, prog, vers, sockp, sendsz, recvsz, tp, flags) + bindaddr.maxlen = bindaddr.len = sizeof (struct sockaddr_in); + bindaddr.buf = raddr; + +- if (__binddynport(fd) == -1) +- goto err; ++ bindresvport(fd, NULL); + cl = clnt_tli_create(fd, nconf, &bindaddr, prog, vers, + sendsz, recvsz); + if (cl) { +@@ -316,6 +313,7 @@ svc_com_create(fd, sendsize, recvsize, netid) + SVCXPRT *svc; + int madefd = FALSE; + int port; ++ struct sockaddr_in sin; + + if ((nconf = __rpc_getconfip(netid)) == NULL) { + (void) syslog(LOG_ERR, "Could not get %s transport", netid); +@@ -332,6 +330,10 @@ svc_com_create(fd, sendsize, recvsize, netid) + madefd = TRUE; + } + ++ memset(&sin, 0, sizeof sin); ++ sin.sin_family = AF_INET; ++ bindresvport(fd, &sin); ++ listen(fd, SOMAXCONN); + svc = svc_tli_create(fd, nconf, NULL, sendsize, recvsize); + (void) freenetconfigent(nconf); + if (svc == NULL) { +diff --git a/src/svc_generic.c b/src/svc_generic.c +index 52a56c2..7aae796 100644 +--- a/src/svc_generic.c ++++ b/src/svc_generic.c +@@ -53,7 +53,6 @@ + #include + + extern int __svc_vc_setflag(SVCXPRT *, int); +-extern int __binddynport(int fd); + + /* + * The highest level interface for server creation. +@@ -221,10 +220,15 @@ svc_tli_create(fd, nconf, bindaddr, sendsz, recvsz) + */ + if (madefd || !__rpc_sockisbound(fd)) { + if (bindaddr == NULL) { +- if (__binddynport(fd) == -1) { +- warnx( ++ if (bindresvport(fd, NULL) < 0) { ++ memset(&ss, 0, sizeof ss); ++ ss.ss_family = si.si_af; ++ if (bind(fd, (struct sockaddr *)(void *)&ss, ++ (socklen_t)si.si_alen) < 0) { ++ warnx( + "svc_tli_create: could not bind to anonymous port"); +- goto freedata; ++ goto freedata; ++ } + } + listen(fd, SOMAXCONN); + } else { diff --git a/libtirpc.changes b/libtirpc.changes index 5b36101..3aa4aac 100644 --- a/libtirpc.changes +++ b/libtirpc.changes @@ -1,3 +1,17 @@ +------------------------------------------------------------------- +Thu Apr 12 08:06:23 UTC 2018 - Thomas.Blume@suse.com + +- fix socket leak introduced by change-rpc-protocol-version-order patch + (bsc#1087925) + - add 0001-Fix-regression-introduced-by-change-rpc-version-orde.patch + +------------------------------------------------------------------- +Thu Apr 5 13:26:43 CEST 2018 - kukuk@suse.de + +- Revert binddynport changes as they break backward compatibility + [brc#1562169]. + - add 002-revert-binddynport.patch + ------------------------------------------------------------------- Thu Mar 15 23:10:46 UTC 2018 - jengelh@inai.de diff --git a/libtirpc.spec b/libtirpc.spec index e2ab83e..b7ea196 100644 --- a/libtirpc.spec +++ b/libtirpc.spec @@ -37,6 +37,9 @@ Source1: baselibs.conf Patch0: 000-bindresvport_blacklist.patch # only needed on openSUSE >= 13.1, SLE >= 12 Patch1: 001-new-rpcbindsock-path.patch +# Revert upstream change until tirpc 1.0.4 with a final solutions comes out +Patch2: 002-revert-binddynport.patch +Patch3: 0001-Fix-regression-introduced-by-change-rpc-version-orde.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build %define debug_package_requires libtirpc3 = %{version}-%{release} @@ -85,9 +88,12 @@ TCP over IPv4. %if 0%{suse_version} >= 1310 %patch1 -p1 %endif +%patch2 -p1 +%patch3 -p1 %build sed -i -e 's|@includedir@/tirpc|@includedir@|g' libtirpc.pc.in +/bin/sh autogen.sh %configure --disable-static \ %if 0%{suse_version} < 1200 --disable-gssapi \