aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/rpcb_clnt.c
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2009-08-09 15:09:40 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2009-08-09 15:09:40 -0400
commit6f2c2db7a46243bd86e3d7ff5f9ff982f26a9fe8 (patch)
tree7b5ce21079d2723a34f1dc982d98a3318c122afe /net/sunrpc/rpcb_clnt.c
parent4116092b92f859e5e9a90c99d740933e651ee8c0 (diff)
SUNRPC: Introduce new xdr_stream-based encoders to rpcb_clnt.c
Replace the open-coded encode logic for rpcbind arguments with an xdr_stream-based implementation, similar to what NFSv4 uses, to better protect against buffer overflows. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc/rpcb_clnt.c')
-rw-r--r--net/sunrpc/rpcb_clnt.c76
1 files changed, 75 insertions, 1 deletions
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 1fb1c070c19d..823d20dbad09 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -708,6 +708,30 @@ static int rpcb_encode_mapping(struct rpc_rqst *req, __be32 *p,
708 return 0; 708 return 0;
709} 709}
710 710
711static int rpcb_enc_mapping(struct rpc_rqst *req, __be32 *p,
712 const struct rpcbind_args *rpcb)
713{
714 struct rpc_task *task = req->rq_task;
715 struct xdr_stream xdr;
716
717 dprintk("RPC: %5u encoding PMAP_%s call (%u, %u, %d, %u)\n",
718 task->tk_pid, task->tk_msg.rpc_proc->p_name,
719 rpcb->r_prog, rpcb->r_vers, rpcb->r_prot, rpcb->r_port);
720
721 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
722
723 p = xdr_reserve_space(&xdr, sizeof(__be32) * RPCB_mappingargs_sz);
724 if (unlikely(p == NULL))
725 return -EIO;
726
727 *p++ = htonl(rpcb->r_prog);
728 *p++ = htonl(rpcb->r_vers);
729 *p++ = htonl(rpcb->r_prot);
730 *p = htonl(rpcb->r_port);
731
732 return 0;
733}
734
711static int rpcb_decode_getport(struct rpc_rqst *req, __be32 *p, 735static int rpcb_decode_getport(struct rpc_rqst *req, __be32 *p,
712 unsigned short *portp) 736 unsigned short *portp)
713{ 737{
@@ -746,6 +770,56 @@ static int rpcb_encode_getaddr(struct rpc_rqst *req, __be32 *p,
746 return 0; 770 return 0;
747} 771}
748 772
773static int encode_rpcb_string(struct xdr_stream *xdr, const char *string,
774 const u32 maxstrlen)
775{
776 u32 len;
777 __be32 *p;
778
779 if (unlikely(string == NULL))
780 return -EIO;
781 len = strlen(string);
782 if (unlikely(len > maxstrlen))
783 return -EIO;
784
785 p = xdr_reserve_space(xdr, sizeof(__be32) + len);
786 if (unlikely(p == NULL))
787 return -EIO;
788 xdr_encode_opaque(p, string, len);
789
790 return 0;
791}
792
793static int rpcb_enc_getaddr(struct rpc_rqst *req, __be32 *p,
794 const struct rpcbind_args *rpcb)
795{
796 struct rpc_task *task = req->rq_task;
797 struct xdr_stream xdr;
798
799 dprintk("RPC: %5u encoding RPCB_%s call (%u, %u, '%s', '%s')\n",
800 task->tk_pid, task->tk_msg.rpc_proc->p_name,
801 rpcb->r_prog, rpcb->r_vers,
802 rpcb->r_netid, rpcb->r_addr);
803
804 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
805
806 p = xdr_reserve_space(&xdr,
807 sizeof(__be32) * (RPCB_program_sz + RPCB_version_sz));
808 if (unlikely(p == NULL))
809 return -EIO;
810 *p++ = htonl(rpcb->r_prog);
811 *p = htonl(rpcb->r_vers);
812
813 if (encode_rpcb_string(&xdr, rpcb->r_netid, RPCBIND_MAXNETIDLEN))
814 return -EIO;
815 if (encode_rpcb_string(&xdr, rpcb->r_addr, RPCBIND_MAXUADDRLEN))
816 return -EIO;
817 if (encode_rpcb_string(&xdr, rpcb->r_owner, RPCB_MAXOWNERLEN))
818 return -EIO;
819
820 return 0;
821}
822
749static int rpcb_decode_getaddr(struct rpc_rqst *req, __be32 *p, 823static int rpcb_decode_getaddr(struct rpc_rqst *req, __be32 *p,
750 unsigned short *portp) 824 unsigned short *portp)
751{ 825{
@@ -812,7 +886,7 @@ out_err:
812#define PROC(proc, argtype, restype) \ 886#define PROC(proc, argtype, restype) \
813 [RPCBPROC_##proc] = { \ 887 [RPCBPROC_##proc] = { \
814 .p_proc = RPCBPROC_##proc, \ 888 .p_proc = RPCBPROC_##proc, \
815 .p_encode = (kxdrproc_t) rpcb_encode_##argtype, \ 889 .p_encode = (kxdrproc_t) rpcb_enc_##argtype, \
816 .p_decode = (kxdrproc_t) rpcb_decode_##restype, \ 890 .p_decode = (kxdrproc_t) rpcb_decode_##restype, \
817 .p_arglen = RPCB_##argtype##args_sz, \ 891 .p_arglen = RPCB_##argtype##args_sz, \
818 .p_replen = RPCB_##restype##res_sz, \ 892 .p_replen = RPCB_##restype##res_sz, \