summaryrefslogtreecommitdiffstats
path: root/usr.sbin/rpcbind
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2015-09-29 18:05:54 +0000
committerdelphij <delphij@FreeBSD.org>2015-09-29 18:05:54 +0000
commit88cb9496ec4805e60fbc82c5c4da1f4ee31f5b9a (patch)
treeb831f6c330d314ce26da5f70adecb1dc161788b9 /usr.sbin/rpcbind
parente8d1e1d737ae470ab51bfca81582786f4bb3cab2 (diff)
downloadFreeBSD-src-88cb9496ec4805e60fbc82c5c4da1f4ee31f5b9a.zip
FreeBSD-src-88cb9496ec4805e60fbc82c5c4da1f4ee31f5b9a.tar.gz
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
Diffstat (limited to 'usr.sbin/rpcbind')
-rw-r--r--usr.sbin/rpcbind/rpcb_svc_com.c24
1 files changed, 19 insertions, 5 deletions
diff --git a/usr.sbin/rpcbind/rpcb_svc_com.c b/usr.sbin/rpcbind/rpcb_svc_com.c
index a362c85..a88f619 100644
--- a/usr.sbin/rpcbind/rpcb_svc_com.c
+++ b/usr.sbin/rpcbind/rpcb_svc_com.c
@@ -47,6 +47,7 @@
#include <rpc/rpc.h>
#include <rpc/rpcb_prot.h>
#include <rpc/svc_dg.h>
+#include <assert.h>
#include <netconfig.h>
#include <errno.h>
#include <syslog.h>
@@ -1047,19 +1048,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);
}
@@ -1067,6 +1080,7 @@ static void
netbuffree(struct netbuf *ap)
{
free(ap->buf);
+ ap->buf = NULL;
free(ap);
}
@@ -1184,7 +1198,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;
}
OpenPOWER on IntegriCloud