aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/rpcb_clnt.c
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2009-08-09 15:09:43 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2009-08-09 15:09:43 -0400
commitc0c077df009f2f329875051ac5283df235288689 (patch)
tree50c0f9b6d78ebbfd711d5bf4c436aa116ed85a51 /net/sunrpc/rpcb_clnt.c
parent7ed0ff983c8ad30bf4e2b9fdbb299a3e3ec08d08 (diff)
SUNRPC: Introduce new xdr_stream-based decoders to rpcb_clnt.c
Replace the open-coded decode logic for PMAP_GETPORT/RPCB_GETADDR with an xdr_stream-based implementation, similar to what NFSv4 uses, to protect against buffer overflows. The new implementation also checks that the incoming port number is reasonable. 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.c80
1 files changed, 77 insertions, 3 deletions
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index fe183af5cc72..88de754e3b02 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -454,7 +454,7 @@ int rpcb_getport_sync(struct sockaddr_in *sin, u32 prog, u32 vers, int prot)
454 struct rpc_message msg = { 454 struct rpc_message msg = {
455 .rpc_proc = &rpcb_procedures2[RPCBPROC_GETPORT], 455 .rpc_proc = &rpcb_procedures2[RPCBPROC_GETPORT],
456 .rpc_argp = &map, 456 .rpc_argp = &map,
457 .rpc_resp = &map.r_port, 457 .rpc_resp = &map,
458 }; 458 };
459 struct rpc_clnt *rpcb_clnt; 459 struct rpc_clnt *rpcb_clnt;
460 int status; 460 int status;
@@ -484,7 +484,7 @@ static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbi
484 struct rpc_message msg = { 484 struct rpc_message msg = {
485 .rpc_proc = proc, 485 .rpc_proc = proc,
486 .rpc_argp = map, 486 .rpc_argp = map,
487 .rpc_resp = &map->r_port, 487 .rpc_resp = map,
488 }; 488 };
489 struct rpc_task_setup task_setup_data = { 489 struct rpc_task_setup task_setup_data = {
490 .rpc_client = rpcb_clnt, 490 .rpc_client = rpcb_clnt,
@@ -727,6 +727,31 @@ static int rpcb_decode_getport(struct rpc_rqst *req, __be32 *p,
727 return 0; 727 return 0;
728} 728}
729 729
730static int rpcb_dec_getport(struct rpc_rqst *req, __be32 *p,
731 struct rpcbind_args *rpcb)
732{
733 struct rpc_task *task = req->rq_task;
734 struct xdr_stream xdr;
735 unsigned long port;
736
737 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
738
739 rpcb->r_port = 0;
740
741 p = xdr_inline_decode(&xdr, sizeof(__be32));
742 if (unlikely(p == NULL))
743 return -EIO;
744
745 port = ntohl(*p);
746 dprintk("RPC: %5u PMAP_%s result: %lu\n", task->tk_pid,
747 task->tk_msg.rpc_proc->p_name, port);
748 if (unlikely(port > USHORT_MAX))
749 return -EIO;
750
751 rpcb->r_port = port;
752 return 0;
753}
754
730static int rpcb_decode_set(struct rpc_rqst *req, __be32 *p, 755static int rpcb_decode_set(struct rpc_rqst *req, __be32 *p,
731 unsigned int *boolp) 756 unsigned int *boolp)
732{ 757{
@@ -871,11 +896,60 @@ out_err:
871 return -EIO; 896 return -EIO;
872} 897}
873 898
899static int rpcb_dec_getaddr(struct rpc_rqst *req, __be32 *p,
900 struct rpcbind_args *rpcb)
901{
902 struct sockaddr_storage address;
903 struct sockaddr *sap = (struct sockaddr *)&address;
904 struct rpc_task *task = req->rq_task;
905 struct xdr_stream xdr;
906 u32 len;
907
908 rpcb->r_port = 0;
909
910 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
911
912 p = xdr_inline_decode(&xdr, sizeof(__be32));
913 if (unlikely(p == NULL))
914 goto out_fail;
915 len = ntohl(*p);
916
917 /*
918 * If the returned universal address is a null string,
919 * the requested RPC service was not registered.
920 */
921 if (len == 0) {
922 dprintk("RPC: %5u RPCB reply: program not registered\n",
923 task->tk_pid);
924 return 0;
925 }
926
927 if (unlikely(len > RPCBIND_MAXUADDRLEN))
928 goto out_fail;
929
930 p = xdr_inline_decode(&xdr, len);
931 if (unlikely(p == NULL))
932 goto out_fail;
933 dprintk("RPC: %5u RPCB_%s reply: %s\n", task->tk_pid,
934 task->tk_msg.rpc_proc->p_name, (char *)p);
935
936 if (rpc_uaddr2sockaddr((char *)p, len, sap, sizeof(address)) == 0)
937 goto out_fail;
938 rpcb->r_port = rpc_get_port(sap);
939
940 return 0;
941
942out_fail:
943 dprintk("RPC: %5u malformed RPCB_%s reply\n",
944 task->tk_pid, task->tk_msg.rpc_proc->p_name);
945 return -EIO;
946}
947
874#define PROC(proc, argtype, restype) \ 948#define PROC(proc, argtype, restype) \
875 [RPCBPROC_##proc] = { \ 949 [RPCBPROC_##proc] = { \
876 .p_proc = RPCBPROC_##proc, \ 950 .p_proc = RPCBPROC_##proc, \
877 .p_encode = (kxdrproc_t) rpcb_enc_##argtype, \ 951 .p_encode = (kxdrproc_t) rpcb_enc_##argtype, \
878 .p_decode = (kxdrproc_t) rpcb_decode_##restype, \ 952 .p_decode = (kxdrproc_t) rpcb_dec_##restype, \
879 .p_arglen = RPCB_##argtype##args_sz, \ 953 .p_arglen = RPCB_##argtype##args_sz, \
880 .p_replen = RPCB_##restype##res_sz, \ 954 .p_replen = RPCB_##restype##res_sz, \
881 .p_statidx = RPCBPROC_##proc, \ 955 .p_statidx = RPCBPROC_##proc, \