summary refs log tree commit diff
path: root/net/sunrpc/rpcb_clnt.c
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2007-08-16 16:03:31 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-10-09 17:16:32 -0400
commit143b6c4008a7928de7e139c3a77a90e4cad8db2c (patch)
tree339ee78286645d5e3704772cdf542ff2bc6aedc2 /net/sunrpc/rpcb_clnt.c
parent756805e7a76bcd2aae07fe31786fe453375e60b1 (diff)
downloadlinux-143b6c4008a7928de7e139c3a77a90e4cad8db2c.tar.gz
SUNRPC: Fix generation of universal addresses for
Fix some problems with rpcbind v3 and v4 queries from the in-kernel rpcbind
client:

1.  The r_addr argument must be a full universal address, not just an IP
address, and

2.  The universal address in r_addr is the address of the remote rpcbind
server, not the RPC service being requested

This addresses bugzilla.kernel.org report 8891 for 2.6.23-rc and greater.

In addition, if the rpcbind client is unable to start the rpcbind request,
make sure not to leak the xprt.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Diffstat (limited to 'net/sunrpc/rpcb_clnt.c')
-rw-r--r--net/sunrpc/rpcb_clnt.c24
1 files changed, 13 insertions, 11 deletions
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 7db75e177e67..0bb6709018de 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -387,6 +387,15 @@ void rpcb_getport_async(struct rpc_task *task)
 	dprintk("RPC: %5u %s: trying rpcbind version %u\n",
 		task->tk_pid, __FUNCTION__, bind_version);
 
+	rpcb_clnt = rpcb_create(clnt->cl_server, &addr, xprt->prot,
+				bind_version, 0);
+	if (IS_ERR(rpcb_clnt)) {
+		status = PTR_ERR(rpcb_clnt);
+		dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n",
+			task->tk_pid, __FUNCTION__, PTR_ERR(rpcb_clnt));
+		goto bailout_nofree;
+	}
+
 	map = kzalloc(sizeof(struct rpcbind_args), GFP_ATOMIC);
 	if (!map) {
 		status = -ENOMEM;
@@ -401,25 +410,18 @@ void rpcb_getport_async(struct rpc_task *task)
 	map->r_xprt = xprt_get(xprt);
 	map->r_netid = (xprt->prot == IPPROTO_TCP) ? RPCB_NETID_TCP :
 						   RPCB_NETID_UDP;
-	memcpy(&map->r_addr, rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR),
-			sizeof(map->r_addr));
+	memcpy(&map->r_addr,
+	       rpc_peeraddr2str(rpcb_clnt, RPC_DISPLAY_UNIVERSAL_ADDR),
+	       sizeof(map->r_addr));
 	map->r_owner = RPCB_OWNER_STRING;	/* ignored for GETADDR */
 
-	rpcb_clnt = rpcb_create(clnt->cl_server, &addr, xprt->prot, bind_version, 0);
-	if (IS_ERR(rpcb_clnt)) {
-		status = PTR_ERR(rpcb_clnt);
-		dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n",
-			task->tk_pid, __FUNCTION__, PTR_ERR(rpcb_clnt));
-		goto bailout;
-	}
-
 	child = rpc_run_task(rpcb_clnt, RPC_TASK_ASYNC, &rpcb_getport_ops, map);
 	rpc_release_client(rpcb_clnt);
 	if (IS_ERR(child)) {
 		status = -EIO;
 		dprintk("RPC: %5u %s: rpc_run_task failed\n",
 			task->tk_pid, __FUNCTION__);
-		goto bailout_nofree;
+		goto bailout;
 	}
 	rpc_put_task(child);