SUNRPC: Make rpcb_decode_getaddr more picky about universal addresses
authorChuck Lever <chuck.lever@oracle.com>
Tue, 11 Sep 2007 22:00:31 +0000 (18:00 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Tue, 9 Oct 2007 21:16:48 +0000 (17:16 -0400)
Add better sanity checking of server replies to the GETVERSADDR reply
decoder.  Change the error return code: EIO is what other XDR decoding
routines return if there is a failure while decoding.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
net/sunrpc/rpcb_clnt.c

index f88ab90..34738c5 100644 (file)
@@ -528,12 +528,19 @@ static int rpcb_decode_getaddr(struct rpc_rqst *req, __be32 *p,
 
        *portp = 0;
        addr_len = ntohl(*p++);
-       if (addr_len > RPCB_MAXADDRLEN)                 /* sanity */
-               return -EINVAL;
-
-       dprintk("RPC:       rpcb_decode_getaddr returned string: '%s'\n",
-                       (char *) p);
 
+       /*
+        * Simple sanity check.  The smallest possible universal
+        * address is an IPv4 address string containing 11 bytes.
+        */
+       if (addr_len < 11 || addr_len > RPCB_MAXADDRLEN)
+               goto out_err;
+
+       /*
+        * Start at the end and walk backwards until the first dot
+        * is encountered.  When the second dot is found, we have
+        * both parts of the port number.
+        */
        addr = (char *)p;
        val = 0;
        first = 1;
@@ -555,8 +562,19 @@ static int rpcb_decode_getaddr(struct rpc_rqst *req, __be32 *p,
                }
        }
 
+       /*
+        * Simple sanity check.  If we never saw a dot in the reply,
+        * then this was probably just garbage.
+        */
+       if (first)
+               goto out_err;
+
        dprintk("RPC:       rpcb_decode_getaddr port=%u\n", *portp);
        return 0;
+
+out_err:
+       dprintk("RPC:       rpcbind server returned malformed reply\n");
+       return -EIO;
 }
 
 #define RPCB_program_sz                (1u)