diff options
| author | Marcel Telka <marcel@telka.sk> | 2017-05-11 09:36:01 +0200 |
|---|---|---|
| committer | Gordon Ross <gwr@nexenta.com> | 2017-05-13 17:12:32 -0400 |
| commit | cfa354e4631308e491ed50bfe99d3cf93cc69bd9 (patch) | |
| tree | 892fa0ec6d021101b57804836663c3abc9d97975 /usr/src/uts/common/rpc | |
| parent | 3897fd1d8d9d8481d79b09d4224c34eaab24fd28 (diff) | |
| download | illumos-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/uts/common/rpc')
| -rw-r--r-- | usr/src/uts/common/rpc/rpcb_prot.c | 69 |
1 files changed, 42 insertions, 27 deletions
diff --git a/usr/src/uts/common/rpc/rpcb_prot.c b/usr/src/uts/common/rpc/rpcb_prot.c index fcc1e5458f..90a711c193 100644 --- a/usr/src/uts/common/rpc/rpcb_prot.c +++ b/usr/src/uts/common/rpc/rpcb_prot.c @@ -37,13 +37,6 @@ * XDR routines for the rpcbinder version 3. */ -#pragma ident "%Z%%M% %I% %E% SMI" - -#if !defined(lint) && defined(SCCSIDS) -static char sccsid[] = "@(#)rpcb_prot.c 1.9 89/04/21 Copyr 1984 Sun Micro"; -#endif - - #include <rpc/rpc.h> #include <rpc/types.h> #include <rpc/xdr.h> @@ -73,7 +66,7 @@ xdr_rpcb(XDR *xdrs, RPCB *objp) bool_t xdr_rpcb_rmtcallargs(XDR *xdrs, struct rpcb_rmtcallargs *objp) { - u_int lenposition, argposition, position; + uint_t lenposition, argposition, position; if (!xdr_rpcprog(xdrs, &objp->prog)) return (FALSE); @@ -86,15 +79,15 @@ xdr_rpcb_rmtcallargs(XDR *xdrs, struct rpcb_rmtcallargs *objp) */ lenposition = XDR_GETPOS(xdrs); if (!xdr_u_int(xdrs, &(objp->arglen))) - return (FALSE); + return (FALSE); argposition = XDR_GETPOS(xdrs); if (!(*(objp->xdr_args))(xdrs, objp->args_ptr)) - return (FALSE); + return (FALSE); position = XDR_GETPOS(xdrs); - objp->arglen = (u_int)position - (u_int)argposition; + objp->arglen = position - argposition; XDR_SETPOS(xdrs, lenposition); if (!xdr_u_int(xdrs, &(objp->arglen))) - return (FALSE); + return (FALSE); XDR_SETPOS(xdrs, position); return (TRUE); } @@ -116,21 +109,43 @@ xdr_rpcb_rmtcallres(XDR *xdrs, struct rpcb_rmtcallres *objp) bool_t xdr_netbuf(XDR *xdrs, struct netbuf *objp) { + 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); + + /* + * 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, - * throw away maxlen, since it doesn't apply to the caller's - * buffer. xdr_bytes will return an error if the buffer isn't big - * enough. + * 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) { - u_int maxlen; - - if (!xdr_u_int(xdrs, &maxlen)) - return (FALSE); - } else { - if (!xdr_u_int(xdrs, (u_int *)&objp->maxlen)) - return (FALSE); - } - return (xdr_bytes(xdrs, (char **)&(objp->buf), - (u_int *)&(objp->len), objp->maxlen)); + 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); } |
