From f5003a757018bf1f26c02f4b331ff07b633d7de0 Mon Sep 17 00:00:00 2001 From: delphij Date: Tue, 29 Sep 2015 18:07:18 +0000 Subject: [PATCH] The Sun RPC framework uses a netbuf structure to represent the transport specific form of a universal transport address. The structure is expected to be opaque to consumers. In the current implementation, the structure contains a pointer to a buffer that holds the actual address. In rpcbind(8), netbuf structures are copied directly, which would result in two netbuf structures that reference to one shared address buffer. When one of the two netbuf structures is freed, access to the other netbuf structure would result in an undefined result that may crash the rpcbind(8) daemon. Fix this by making a copy of the buffer that is going to be freed instead of doing a shallow copy. Security: FreeBSD-SA-15:24.rpcbind Security: CVE-2015-7236 Approved by: so git-svn-id: https://svn.freebsd.org/base/releng/10.2@288385 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- UPDATING | 4 ++++ sys/conf/newvers.sh | 2 +- usr.sbin/rpcbind/rpcb_svc_com.c | 24 +++++++++++++++++++----- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/UPDATING b/UPDATING index c877003cc..48ab7fd71 100644 --- a/UPDATING +++ b/UPDATING @@ -16,6 +16,10 @@ from older versions of FreeBSD, try WITHOUT_CLANG to bootstrap to the tip of stable/10, and then rebuild without this option. The bootstrap process from older version of current is a bit fragile. +20150929: p4 FreeBSD-SA-15:24.rpcbind + + Fix rpcbind(8) remote denial of service. [SA-15:24] + 20150916: p3 FreeBSD-EN-15:16.pw FreeBSD-EN-15:17.libc FreeBSD-EN-15:18.pkg diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh index 2c29cee14..a026b66f1 100644 --- a/sys/conf/newvers.sh +++ b/sys/conf/newvers.sh @@ -32,7 +32,7 @@ TYPE="FreeBSD" REVISION="10.2" -BRANCH="RELEASE-p3" +BRANCH="RELEASE-p4" if [ "X${BRANCH_OVERRIDE}" != "X" ]; then BRANCH=${BRANCH_OVERRIDE} fi diff --git a/usr.sbin/rpcbind/rpcb_svc_com.c b/usr.sbin/rpcbind/rpcb_svc_com.c index f90dc5964..a72527343 100644 --- a/usr.sbin/rpcbind/rpcb_svc_com.c +++ b/usr.sbin/rpcbind/rpcb_svc_com.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -1048,19 +1049,31 @@ netbufcmp(struct netbuf *n1, struct netbuf *n2) return ((n1->len != n2->len) || memcmp(n1->buf, n2->buf, n1->len)); } +static bool_t +netbuf_copybuf(struct netbuf *dst, const struct netbuf *src) +{ + + assert(dst->buf == NULL); + + if ((dst->buf = malloc(src->len)) == NULL) + return (FALSE); + + dst->maxlen = dst->len = src->len; + memcpy(dst->buf, src->buf, src->len); + return (TRUE); +} + static struct netbuf * netbufdup(struct netbuf *ap) { struct netbuf *np; - if ((np = malloc(sizeof(struct netbuf))) == NULL) + if ((np = calloc(1, sizeof(struct netbuf))) == NULL) return (NULL); - if ((np->buf = malloc(ap->len)) == NULL) { + if (netbuf_copybuf(np, ap) == FALSE) { free(np); return (NULL); } - np->maxlen = np->len = ap->len; - memcpy(np->buf, ap->buf, ap->len); return (np); } @@ -1068,6 +1081,7 @@ static void netbuffree(struct netbuf *ap) { free(ap->buf); + ap->buf = NULL; free(ap); } @@ -1185,7 +1199,7 @@ xprt_set_caller(SVCXPRT *xprt, struct finfo *fi) { u_int32_t *xidp; - *(svc_getrpccaller(xprt)) = *(fi->caller_addr); + netbuf_copybuf(svc_getrpccaller(xprt), fi->caller_addr); xidp = __rpcb_get_dg_xidp(xprt); *xidp = fi->caller_xid; } -- 2.42.0