diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2007-08-16 16:03:31 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-10-09 17:16:32 -0400 |
commit | 143b6c4008a7928de7e139c3a77a90e4cad8db2c (patch) | |
tree | 339ee78286645d5e3704772cdf542ff2bc6aedc2 /net/sunrpc | |
parent | 756805e7a76bcd2aae07fe31786fe453375e60b1 (diff) |
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')
-rw-r--r-- | net/sunrpc/rpcb_clnt.c | 24 |
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) | |||
387 | dprintk("RPC: %5u %s: trying rpcbind version %u\n", | 387 | dprintk("RPC: %5u %s: trying rpcbind version %u\n", |
388 | task->tk_pid, __FUNCTION__, bind_version); | 388 | task->tk_pid, __FUNCTION__, bind_version); |
389 | 389 | ||
390 | rpcb_clnt = rpcb_create(clnt->cl_server, &addr, xprt->prot, | ||
391 | bind_version, 0); | ||
392 | if (IS_ERR(rpcb_clnt)) { | ||
393 | status = PTR_ERR(rpcb_clnt); | ||
394 | dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n", | ||
395 | task->tk_pid, __FUNCTION__, PTR_ERR(rpcb_clnt)); | ||
396 | goto bailout_nofree; | ||
397 | } | ||
398 | |||
390 | map = kzalloc(sizeof(struct rpcbind_args), GFP_ATOMIC); | 399 | map = kzalloc(sizeof(struct rpcbind_args), GFP_ATOMIC); |
391 | if (!map) { | 400 | if (!map) { |
392 | status = -ENOMEM; | 401 | status = -ENOMEM; |
@@ -401,25 +410,18 @@ void rpcb_getport_async(struct rpc_task *task) | |||
401 | map->r_xprt = xprt_get(xprt); | 410 | map->r_xprt = xprt_get(xprt); |
402 | map->r_netid = (xprt->prot == IPPROTO_TCP) ? RPCB_NETID_TCP : | 411 | map->r_netid = (xprt->prot == IPPROTO_TCP) ? RPCB_NETID_TCP : |
403 | RPCB_NETID_UDP; | 412 | RPCB_NETID_UDP; |
404 | memcpy(&map->r_addr, rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR), | 413 | memcpy(&map->r_addr, |
405 | sizeof(map->r_addr)); | 414 | rpc_peeraddr2str(rpcb_clnt, RPC_DISPLAY_UNIVERSAL_ADDR), |
415 | sizeof(map->r_addr)); | ||
406 | map->r_owner = RPCB_OWNER_STRING; /* ignored for GETADDR */ | 416 | map->r_owner = RPCB_OWNER_STRING; /* ignored for GETADDR */ |
407 | 417 | ||
408 | rpcb_clnt = rpcb_create(clnt->cl_server, &addr, xprt->prot, bind_version, 0); | ||
409 | if (IS_ERR(rpcb_clnt)) { | ||
410 | status = PTR_ERR(rpcb_clnt); | ||
411 | dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n", | ||
412 | task->tk_pid, __FUNCTION__, PTR_ERR(rpcb_clnt)); | ||
413 | goto bailout; | ||
414 | } | ||
415 | |||
416 | child = rpc_run_task(rpcb_clnt, RPC_TASK_ASYNC, &rpcb_getport_ops, map); | 418 | child = rpc_run_task(rpcb_clnt, RPC_TASK_ASYNC, &rpcb_getport_ops, map); |
417 | rpc_release_client(rpcb_clnt); | 419 | rpc_release_client(rpcb_clnt); |
418 | if (IS_ERR(child)) { | 420 | if (IS_ERR(child)) { |
419 | status = -EIO; | 421 | status = -EIO; |
420 | dprintk("RPC: %5u %s: rpc_run_task failed\n", | 422 | dprintk("RPC: %5u %s: rpc_run_task failed\n", |
421 | task->tk_pid, __FUNCTION__); | 423 | task->tk_pid, __FUNCTION__); |
422 | goto bailout_nofree; | 424 | goto bailout; |
423 | } | 425 | } |
424 | rpc_put_task(child); | 426 | rpc_put_task(child); |
425 | 427 | ||