diff -Nru libtirpc-0.2.2/debian/changelog libtirpc-0.2.2/debian/changelog --- libtirpc-0.2.2/debian/changelog 2013-12-19 00:03:37.000000000 +0000 +++ libtirpc-0.2.2/debian/changelog 2018-09-04 12:31:02.000000000 +0000 @@ -1,3 +1,18 @@ +libtirpc (0.2.2-5ubuntu2.1) trusty-security; urgency=medium + + * SECURITY UPDATE: Denial of service + - debian/patches/CVE-2016-4429.diff: fix in src/clnt_dg.c. + - CVE-2016-4429 + * SECURITY UPDATE: Denial of service + - debian/patches/CVE-2017-8779.patch: fix in src/rpc_generic.c, + src/rpcb_prot.c, src/rpcb_st_xdr.c, src/xdr.c. + - CVE-2017-8779 + * SECURITY UPDATE: Denial of service + - debian/patches/CVE-2018-14622.patch: fix in src/svc_c.c. + - CVE-2018-14622 + + -- Leonidas S. Barbosa Tue, 04 Sep 2018 09:30:25 -0300 + libtirpc (0.2.2-5ubuntu2) trusty; urgency=medium * Build using dh-autoreconf. diff -Nru libtirpc-0.2.2/debian/control libtirpc-0.2.2/debian/control --- libtirpc-0.2.2/debian/control 2013-12-19 00:01:38.000000000 +0000 +++ libtirpc-0.2.2/debian/control 2018-09-04 12:31:06.000000000 +0000 @@ -1,6 +1,7 @@ Source: libtirpc Priority: standard -Maintainer: Steinar H. Gunderson +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Steinar H. Gunderson Build-Depends: debhelper (>= 8.1.3), autotools-dev, libtool, libgssglue-dev, pkg-config, dh-autoreconf Standards-Version: 3.9.2 Section: libs diff -Nru libtirpc-0.2.2/debian/patches/CVE-2016-4429.diff libtirpc-0.2.2/debian/patches/CVE-2016-4429.diff --- libtirpc-0.2.2/debian/patches/CVE-2016-4429.diff 1970-01-01 00:00:00.000000000 +0000 +++ libtirpc-0.2.2/debian/patches/CVE-2016-4429.diff 2018-09-04 13:08:15.000000000 +0000 @@ -0,0 +1,49 @@ +From bc779a1a5b3035133024b21e2f339fe4219fb11c Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Mon, 23 May 2016 20:18:34 +0200 +Subject: [PATCH] CVE-2016-4429: tirpc: Do not use alloca in clntudp_call [BZ #20112] + +The call is technically in a loop, and under certain circumstances +(which are quite difficult to reproduce in a test case), alloca +can be invoked repeatedly during a single call to clntudp_call. +As a result, the available stack space can be exhausted (even +though individual alloca sizes are bounded implicitly by what +can fit into a UDP packet, as a side effect of the earlier +successful send operation). + +[zeha@d.o: edited for libtirpc] +diff --git a/src/clnt_dg.c b/src/clnt_dg.c +index 79fed5d..aa7e58b 100644 +--- a/src/clnt_dg.c ++++ b/src/clnt_dg.c +@@ -430,9 +430,15 @@ get_reply: + struct sockaddr_in err_addr; + struct sockaddr_in *sin = (struct sockaddr_in *)&cu->cu_raddr; + struct iovec iov; +- char *cbuf = (char *) alloca (outlen + 256); ++ char *cbuf = malloc (outlen + 256); + int ret; + ++ if (cbuf == NULL) ++ { ++ cu->cu_error.re_errno = errno; ++ return (cu->cu_error.re_status = RPC_CANTRECV); ++ } ++ + iov.iov_base = cbuf + 256; + iov.iov_len = outlen; + msg.msg_name = (void *) &err_addr; +@@ -457,11 +463,13 @@ get_reply: + cmsg = CMSG_NXTHDR (&msg, cmsg)) + if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR) + { ++ free (cbuf); + e = (struct sock_extended_err *) CMSG_DATA(cmsg); + cu->cu_error.re_errno = e->ee_errno; + release_fd_lock(cu->cu_fd, mask); + return (cu->cu_error.re_status = RPC_CANTRECV); + } ++ free (cbuf); + } + #endif + diff -Nru libtirpc-0.2.2/debian/patches/CVE-2017-8779.patch libtirpc-0.2.2/debian/patches/CVE-2017-8779.patch --- libtirpc-0.2.2/debian/patches/CVE-2017-8779.patch 1970-01-01 00:00:00.000000000 +0000 +++ libtirpc-0.2.2/debian/patches/CVE-2017-8779.patch 2018-09-04 12:29:36.000000000 +0000 @@ -0,0 +1,273 @@ +Description: CVE-2017-8779: Memory leak when failing to parse XDR strings or bytearrays +Origin: vendor +Bug-Debian: https://bugs.debian.org/861834 +Forwarded: not-needed +Author: Guido Vranken +Reviewed-by: Salvatore Bonaccorso +Last-Update: 2017-05-05 + +--- + src/rpc_generic.c | 8 ++++++++ + src/rpcb_prot.c | 22 ++++++++++++++-------- + src/rpcb_st_xdr.c | 9 +++++---- + src/xdr.c | 30 +++++++++++++++++++++++++----- + 4 files changed, 52 insertions(+), 17 deletions(-) + +diff --git a/src/rpc_generic.c b/src/rpc_generic.c +index 509fb36..a502d7b 100644 +--- a/src/rpc_generic.c ++++ b/src/rpc_generic.c +@@ -613,6 +613,9 @@ __rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf) + + switch (af) { + case AF_INET: ++ if (nbuf->len < sizeof(*sin)) { ++ return NULL; ++ } + sin = nbuf->buf; + if (inet_ntop(af, &sin->sin_addr, namebuf, sizeof namebuf) + == NULL) +@@ -624,6 +627,9 @@ __rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf) + break; + #ifdef INET6 + case AF_INET6: ++ if (nbuf->len < sizeof(*sin6)) { ++ return NULL; ++ } + sin6 = nbuf->buf; + if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6) + == NULL) +@@ -666,6 +672,8 @@ __rpc_uaddr2taddr_af(int af, const char *uaddr) + + port = 0; + sin = NULL; ++ if (uaddr == NULL) ++ return NULL; + addrstr = strdup(uaddr); + if (addrstr == NULL) + return NULL; +diff --git a/src/rpcb_prot.c b/src/rpcb_prot.c +index 43fd385..a923c8e 100644 +--- a/src/rpcb_prot.c ++++ b/src/rpcb_prot.c +@@ -41,6 +41,7 @@ + #include + #include + #include ++#include "rpc_com.h" + + bool_t + xdr_rpcb(xdrs, objp) +@@ -53,13 +54,13 @@ xdr_rpcb(xdrs, objp) + if (!xdr_u_int32_t(xdrs, &objp->r_vers)) { + return (FALSE); + } +- if (!xdr_string(xdrs, &objp->r_netid, (u_int)~0)) { ++ if (!xdr_string(xdrs, &objp->r_netid, RPC_MAXDATASIZE)) { + return (FALSE); + } +- if (!xdr_string(xdrs, &objp->r_addr, (u_int)~0)) { ++ if (!xdr_string(xdrs, &objp->r_addr, RPC_MAXDATASIZE)) { + return (FALSE); + } +- if (!xdr_string(xdrs, &objp->r_owner, (u_int)~0)) { ++ if (!xdr_string(xdrs, &objp->r_owner, RPC_MAXDATASIZE)) { + return (FALSE); + } + return (TRUE); +@@ -159,19 +160,19 @@ xdr_rpcb_entry(xdrs, objp) + XDR *xdrs; + rpcb_entry *objp; + { +- if (!xdr_string(xdrs, &objp->r_maddr, (u_int)~0)) { ++ if (!xdr_string(xdrs, &objp->r_maddr, RPC_MAXDATASIZE)) { + return (FALSE); + } +- if (!xdr_string(xdrs, &objp->r_nc_netid, (u_int)~0)) { ++ if (!xdr_string(xdrs, &objp->r_nc_netid, RPC_MAXDATASIZE)) { + return (FALSE); + } + if (!xdr_u_int32_t(xdrs, &objp->r_nc_semantics)) { + return (FALSE); + } +- if (!xdr_string(xdrs, &objp->r_nc_protofmly, (u_int)~0)) { ++ if (!xdr_string(xdrs, &objp->r_nc_protofmly, RPC_MAXDATASIZE)) { + return (FALSE); + } +- if (!xdr_string(xdrs, &objp->r_nc_proto, (u_int)~0)) { ++ if (!xdr_string(xdrs, &objp->r_nc_proto, RPC_MAXDATASIZE)) { + return (FALSE); + } + return (TRUE); +@@ -292,7 +293,7 @@ xdr_rpcb_rmtcallres(xdrs, p) + bool_t dummy; + struct r_rpcb_rmtcallres *objp = (struct r_rpcb_rmtcallres *)(void *)p; + +- if (!xdr_string(xdrs, &objp->addr, (u_int)~0)) { ++ if (!xdr_string(xdrs, &objp->addr, RPC_MAXDATASIZE)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->results.results_len)) { +@@ -312,6 +313,11 @@ xdr_netbuf(xdrs, objp) + if (!xdr_u_int32_t(xdrs, (u_int32_t *) &objp->maxlen)) { + return (FALSE); + } ++ ++ if (objp->maxlen > RPC_MAXDATASIZE) { ++ return (FALSE); ++ } ++ + dummy = xdr_bytes(xdrs, (char **)&(objp->buf), + (u_int *)&(objp->len), objp->maxlen); + return (dummy); +diff --git a/src/rpcb_st_xdr.c b/src/rpcb_st_xdr.c +index c5d3575..1bd5cd8 100644 +--- a/src/rpcb_st_xdr.c ++++ b/src/rpcb_st_xdr.c +@@ -38,6 +38,7 @@ + #include + + #include ++#include "rpc_com.h" + + /* Link list of all the stats about getport and getaddr */ + +@@ -59,7 +60,7 @@ xdr_rpcbs_addrlist(xdrs, objp) + if (!xdr_int(xdrs, &objp->failure)) { + return (FALSE); + } +- if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) { ++ if (!xdr_string(xdrs, &objp->netid, RPC_MAXDATASIZE)) { + return (FALSE); + } + +@@ -110,7 +111,7 @@ xdr_rpcbs_rmtcalllist(xdrs, objp) + IXDR_PUT_INT32(buf, objp->failure); + IXDR_PUT_INT32(buf, objp->indirect); + } +- if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) { ++ if (!xdr_string(xdrs, &objp->netid, RPC_MAXDATASIZE)) { + return (FALSE); + } + if (!xdr_pointer(xdrs, (char **)&objp->next, +@@ -148,7 +149,7 @@ xdr_rpcbs_rmtcalllist(xdrs, objp) + objp->failure = (int)IXDR_GET_INT32(buf); + objp->indirect = (int)IXDR_GET_INT32(buf); + } +- if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) { ++ if (!xdr_string(xdrs, &objp->netid, RPC_MAXDATASIZE)) { + return (FALSE); + } + if (!xdr_pointer(xdrs, (char **)&objp->next, +@@ -176,7 +177,7 @@ xdr_rpcbs_rmtcalllist(xdrs, objp) + if (!xdr_int(xdrs, &objp->indirect)) { + return (FALSE); + } +- if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) { ++ if (!xdr_string(xdrs, &objp->netid, RPC_MAXDATASIZE)) { + return (FALSE); + } + if (!xdr_pointer(xdrs, (char **)&objp->next, +diff --git a/src/xdr.c b/src/xdr.c +index fb31f54..9300d5d 100644 +--- a/src/xdr.c ++++ b/src/xdr.c +@@ -43,8 +43,10 @@ + #include + #include + ++#include + #include + #include ++#include + + typedef quad_t longlong_t; /* ANSI long long type */ + typedef u_quad_t u_longlong_t; /* ANSI unsigned long long type */ +@@ -54,7 +56,6 @@ typedef u_quad_t u_longlong_t; /* ANSI unsigned long long type */ + */ + #define XDR_FALSE ((long) 0) + #define XDR_TRUE ((long) 1) +-#define LASTUNSIGNED ((u_int) 0-1) + + /* + * for unit alignment +@@ -532,6 +533,7 @@ xdr_bytes(xdrs, cpp, sizep, maxsize) + { + char *sp = *cpp; /* sp is the actual string pointer */ + u_int nodesize; ++ bool_t ret, allocated = FALSE; + + /* + * first deal with the length since xdr bytes are counted +@@ -555,6 +557,7 @@ xdr_bytes(xdrs, cpp, sizep, maxsize) + } + if (sp == NULL) { + *cpp = sp = mem_alloc(nodesize); ++ allocated = TRUE; + } + if (sp == NULL) { + warnx("xdr_bytes: out of memory"); +@@ -563,7 +566,14 @@ xdr_bytes(xdrs, cpp, sizep, maxsize) + /* FALLTHROUGH */ + + case XDR_ENCODE: +- return (xdr_opaque(xdrs, sp, nodesize)); ++ ret = xdr_opaque(xdrs, sp, nodesize); ++ if ((xdrs->x_op == XDR_DECODE) && (ret == FALSE)) { ++ if (allocated == TRUE) { ++ free(sp); ++ *cpp = NULL; ++ } ++ } ++ return (ret); + + case XDR_FREE: + if (sp != NULL) { +@@ -657,6 +667,7 @@ xdr_string(xdrs, cpp, maxsize) + char *sp = *cpp; /* sp is the actual string pointer */ + u_int size; + u_int nodesize; ++ bool_t ret, allocated = FALSE; + + /* + * first deal with the length since xdr strings are counted-strings +@@ -696,8 +707,10 @@ xdr_string(xdrs, cpp, maxsize) + switch (xdrs->x_op) { + + case XDR_DECODE: +- if (sp == NULL) ++ if (sp == NULL) { + *cpp = sp = mem_alloc(nodesize); ++ allocated = TRUE; ++ } + if (sp == NULL) { + warnx("xdr_string: out of memory"); + return (FALSE); +@@ -706,7 +719,14 @@ xdr_string(xdrs, cpp, maxsize) + /* FALLTHROUGH */ + + case XDR_ENCODE: +- return (xdr_opaque(xdrs, sp, size)); ++ ret = xdr_opaque(xdrs, sp, size); ++ if ((xdrs->x_op == XDR_DECODE) && (ret == FALSE)) { ++ if (allocated == TRUE) { ++ free(sp); ++ *cpp = NULL; ++ } ++ } ++ return (ret); + + case XDR_FREE: + mem_free(sp, nodesize); +@@ -726,7 +746,7 @@ xdr_wrapstring(xdrs, cpp) + XDR *xdrs; + char **cpp; + { +- return xdr_string(xdrs, cpp, LASTUNSIGNED); ++ return xdr_string(xdrs, cpp, RPC_MAXDATASIZE); + } + + /* +-- +2.7.4 + diff -Nru libtirpc-0.2.2/debian/patches/CVE-2018-14622.patch libtirpc-0.2.2/debian/patches/CVE-2018-14622.patch --- libtirpc-0.2.2/debian/patches/CVE-2018-14622.patch 1970-01-01 00:00:00.000000000 +0000 +++ libtirpc-0.2.2/debian/patches/CVE-2018-14622.patch 2018-09-04 12:29:48.000000000 +0000 @@ -0,0 +1,23 @@ +From 1c77f7a869bdea2a34799d774460d1f9983d45f0 Mon Sep 17 00:00:00 2001 +From: Ditang Chen +Date: Mon, 13 Jul 2015 10:36:16 -0400 +Subject: [PATCH] rendezvous_request: check the makefd_xprt return value + +xprt may return NULL, so check the return value is necessary. + +Reviewed-by: Chuck Lever +Signed-off-by: Ditang Chen +Signed-off-by: Steve Dickson +Index: libtirpc-0.2.2/src/svc_vc.c +=================================================================== +--- libtirpc-0.2.2.orig/src/svc_vc.c ++++ libtirpc-0.2.2/src/svc_vc.c +@@ -336,6 +336,8 @@ again: + */ + + newxprt = makefd_xprt(sock, r->sendsize, r->recvsize); ++ if (!newxprt) ++ return (FALSE); + + if (!__rpc_set_netbuf(&newxprt->xp_rtaddr, &addr, len)) + return (FALSE); diff -Nru libtirpc-0.2.2/debian/patches/series libtirpc-0.2.2/debian/patches/series --- libtirpc-0.2.2/debian/patches/series 2013-08-17 08:37:41.000000000 +0000 +++ libtirpc-0.2.2/debian/patches/series 2018-09-04 13:08:15.000000000 +0000 @@ -3,3 +3,6 @@ 03-kfreebsd.diff 04-fix-memory-leak.diff config-updates.diff +CVE-2016-4429.diff +CVE-2017-8779.patch +CVE-2018-14622.patch