aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2015-01-30 18:12:28 -0500
committerTrond Myklebust <trond.myklebust@primarydata.com>2015-02-03 16:40:17 -0500
commit03a9a42a1a7e5b3e7919ddfacc1d1cc81882a955 (patch)
treeeb1e9497ef3e6dd0090cfb054cfe08b6bbea5d6a /net/sunrpc
parente2c63e091e29786a34ecf42c169e627a3d1d96d7 (diff)
SUNRPC: NULL utsname dereference on NFS umount during namespace cleanup
Fix an Oopsable condition when nsm_mon_unmon is called as part of the namespace cleanup, which now apparently happens after the utsname has been freed. Link: http://lkml.kernel.org/r/20150125220604.090121ae@neptune.home Reported-by: Bruno Prémont <bonbons@linux-vserver.org> Cc: stable@vger.kernel.org # 3.18 Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/clnt.c12
-rw-r--r--net/sunrpc/rpcb_clnt.c8
2 files changed, 13 insertions, 7 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 05da12a33945..3f5d4d48f0cb 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -286,10 +286,8 @@ static struct rpc_xprt *rpc_clnt_set_transport(struct rpc_clnt *clnt,
286 286
287static void rpc_clnt_set_nodename(struct rpc_clnt *clnt, const char *nodename) 287static void rpc_clnt_set_nodename(struct rpc_clnt *clnt, const char *nodename)
288{ 288{
289 clnt->cl_nodelen = strlen(nodename); 289 clnt->cl_nodelen = strlcpy(clnt->cl_nodename,
290 if (clnt->cl_nodelen > UNX_MAXNODENAME) 290 nodename, sizeof(clnt->cl_nodename));
291 clnt->cl_nodelen = UNX_MAXNODENAME;
292 memcpy(clnt->cl_nodename, nodename, clnt->cl_nodelen);
293} 291}
294 292
295static int rpc_client_register(struct rpc_clnt *clnt, 293static int rpc_client_register(struct rpc_clnt *clnt,
@@ -365,6 +363,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args,
365 const struct rpc_version *version; 363 const struct rpc_version *version;
366 struct rpc_clnt *clnt = NULL; 364 struct rpc_clnt *clnt = NULL;
367 const struct rpc_timeout *timeout; 365 const struct rpc_timeout *timeout;
366 const char *nodename = args->nodename;
368 int err; 367 int err;
369 368
370 /* sanity check the name before trying to print it */ 369 /* sanity check the name before trying to print it */
@@ -420,8 +419,10 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args,
420 419
421 atomic_set(&clnt->cl_count, 1); 420 atomic_set(&clnt->cl_count, 1);
422 421
422 if (nodename == NULL)
423 nodename = utsname()->nodename;
423 /* save the nodename */ 424 /* save the nodename */
424 rpc_clnt_set_nodename(clnt, utsname()->nodename); 425 rpc_clnt_set_nodename(clnt, nodename);
425 426
426 err = rpc_client_register(clnt, args->authflavor, args->client_name); 427 err = rpc_client_register(clnt, args->authflavor, args->client_name);
427 if (err) 428 if (err)
@@ -576,6 +577,7 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args,
576 if (xprt == NULL) 577 if (xprt == NULL)
577 goto out_err; 578 goto out_err;
578 args->servername = xprt->servername; 579 args->servername = xprt->servername;
580 args->nodename = clnt->cl_nodename;
579 581
580 new = rpc_new_client(args, xprt, clnt); 582 new = rpc_new_client(args, xprt, clnt);
581 if (IS_ERR(new)) { 583 if (IS_ERR(new)) {
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 05202012bcfc..cf5770d8f49a 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -355,7 +355,8 @@ out:
355 return result; 355 return result;
356} 356}
357 357
358static struct rpc_clnt *rpcb_create(struct net *net, const char *hostname, 358static struct rpc_clnt *rpcb_create(struct net *net, const char *nodename,
359 const char *hostname,
359 struct sockaddr *srvaddr, size_t salen, 360 struct sockaddr *srvaddr, size_t salen,
360 int proto, u32 version) 361 int proto, u32 version)
361{ 362{
@@ -365,6 +366,7 @@ static struct rpc_clnt *rpcb_create(struct net *net, const char *hostname,
365 .address = srvaddr, 366 .address = srvaddr,
366 .addrsize = salen, 367 .addrsize = salen,
367 .servername = hostname, 368 .servername = hostname,
369 .nodename = nodename,
368 .program = &rpcb_program, 370 .program = &rpcb_program,
369 .version = version, 371 .version = version,
370 .authflavor = RPC_AUTH_UNIX, 372 .authflavor = RPC_AUTH_UNIX,
@@ -740,7 +742,9 @@ void rpcb_getport_async(struct rpc_task *task)
740 dprintk("RPC: %5u %s: trying rpcbind version %u\n", 742 dprintk("RPC: %5u %s: trying rpcbind version %u\n",
741 task->tk_pid, __func__, bind_version); 743 task->tk_pid, __func__, bind_version);
742 744
743 rpcb_clnt = rpcb_create(xprt->xprt_net, xprt->servername, sap, salen, 745 rpcb_clnt = rpcb_create(xprt->xprt_net,
746 clnt->cl_nodename,
747 xprt->servername, sap, salen,
744 xprt->prot, bind_version); 748 xprt->prot, bind_version);
745 if (IS_ERR(rpcb_clnt)) { 749 if (IS_ERR(rpcb_clnt)) {
746 status = PTR_ERR(rpcb_clnt); 750 status = PTR_ERR(rpcb_clnt);