summaryrefslogtreecommitdiff
path: root/usr/src/lib/libnsl/rpc/rpcb_prot.c
diff options
context:
space:
mode:
authorMarcel Telka <marcel@telka.sk>2017-05-11 09:36:01 +0200
committerGordon Ross <gwr@nexenta.com>2017-05-13 17:12:32 -0400
commitcfa354e4631308e491ed50bfe99d3cf93cc69bd9 (patch)
tree892fa0ec6d021101b57804836663c3abc9d97975 /usr/src/lib/libnsl/rpc/rpcb_prot.c
parent3897fd1d8d9d8481d79b09d4224c34eaab24fd28 (diff)
downloadillumos-joyent-cfa354e4631308e491ed50bfe99d3cf93cc69bd9.tar.gz
8180 Invalid netbuf decoded by xdr_netbuf()
Reviewed by: Arne Jansen <arne@die-jansens.de> Reviewed by: Yuri Pankov <yuri.pankov@gmail.com> Reviewed by: Vitaliy Gusev <gusev.vitaliy@icloud.com> Approved by: Gordon Ross <gordon.w.ross@gmail.com>
Diffstat (limited to 'usr/src/lib/libnsl/rpc/rpcb_prot.c')
-rw-r--r--usr/src/lib/libnsl/rpc/rpcb_prot.c45
1 files changed, 39 insertions, 6 deletions
diff --git a/usr/src/lib/libnsl/rpc/rpcb_prot.c b/usr/src/lib/libnsl/rpc/rpcb_prot.c
index d81e7e19f8..464ce69743 100644
--- a/usr/src/lib/libnsl/rpc/rpcb_prot.c
+++ b/usr/src/lib/libnsl/rpc/rpcb_prot.c
@@ -33,8 +33,6 @@
* California.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* XDR routines for the rpcbinder version 3.
*/
@@ -180,7 +178,7 @@ xdr_rpcb_entry_list_ptr(XDR *xdrs, rpcb_entry_list_ptr *rp)
next = (*rp)->rpcb_entry_next;
if (!xdr_reference(xdrs, (caddr_t *)rp,
(uint_t)sizeof (rpcb_entry_list),
- (xdrproc_t)xdr_rpcb_entry))
+ (xdrproc_t)xdr_rpcb_entry))
return (FALSE);
if (freeing) {
next_copy = next;
@@ -256,8 +254,43 @@ xdr_rpcb_rmtcallres(XDR *xdrs, struct r_rpcb_rmtcallres *objp)
bool_t
xdr_netbuf(XDR *xdrs, struct netbuf *objp)
{
- if (!xdr_u_int(xdrs, (uint_t *)&objp->maxlen))
+ bool_t res;
+
+ /*
+ * Save the passed in maxlen value and buf pointer. We might
+ * need them later.
+ */
+ uint_t maxlen_save = objp->maxlen;
+ void *buf_save = objp->buf;
+
+ if (!xdr_u_int(xdrs, &objp->maxlen))
return (FALSE);
- return (xdr_bytes(xdrs, (char **)&(objp->buf),
- (uint_t *)&(objp->len), objp->maxlen));
+
+ /*
+ * We need to free maxlen, not len, so do it explicitly now.
+ */
+ if (xdrs->x_op == XDR_FREE)
+ return (xdr_bytes(xdrs, &objp->buf, &objp->maxlen,
+ objp->maxlen));
+
+ /*
+ * If we're decoding and the caller has already allocated a
+ * buffer restore the maxlen value since the decoded value
+ * doesn't apply to the caller's buffer. xdr_bytes() will
+ * return an error if the buffer isn't big enough.
+ */
+ if (xdrs->x_op == XDR_DECODE && objp->buf != NULL)
+ objp->maxlen = maxlen_save;
+
+ res = xdr_bytes(xdrs, &objp->buf, &objp->len, objp->maxlen);
+
+ /*
+ * If we are decoding and the buffer was allocated in the
+ * xdr_bytes() function we need to set maxlen properly to
+ * follow the netbuf semantics.
+ */
+ if (xdrs->x_op == XDR_DECODE && objp->buf != buf_save)
+ objp->maxlen = objp->len;
+
+ return (res);
}