Re: Patch "SUNRPC: NULL utsname dereference on NFS umount during namespace cleanup" has been added to the 3.14-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 03 March 2015 Luis Henriques <luis.henriques@xxxxxxxxxxxxx> wrote:
> On Sat, Feb 28, 2015 at 03:06:04PM -0800, Greg Kroah-Hartman wrote:
> > 
> > This is a note to let you know that I've just added the patch titled
> > 
> >     SUNRPC: NULL utsname dereference on NFS umount during namespace cleanup
> > 
> > to the 3.14-stable tree which can be found at:
> >     http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
> > 
> > The filename of the patch is:
> >      sunrpc-null-utsname-dereference-on-nfs-umount-during-namespace-cleanup.patch
> > and it can be found in the queue-3.14 subdirectory.
> > 
> > If you, or anyone else, feels it should not be added to the stable tree,
> > please let <stable@xxxxxxxxxxxxxxx> know about it.
> >
> 
> Maybe this is actually applicable to the 3.14 kernel, but it was
> tagged for stable 3.18.  Trond?  Bruno?

I've first hit the bug on 3.18 so I can't tell if it can be triggered
with older releases.

As I could pin-point the cause of crash and a possible fix/work-around I
did not bisect to find out what made the NULL-pointer dereference possible.

Guess is that a change in ordering of namespace cleanup process made the
issue surface.

On the other hand, to be confirmed by Trond, the use of utsname may still
cause some issues due to hostname changes in some namespaces other than
the one which initially mounted the share. The issues here would rather be
at a higher level between nfs client and server (name used being different
from expected name).

Bruno

> Cheers,
> --
> Luís
> 
> > 
> > From 03a9a42a1a7e5b3e7919ddfacc1d1cc81882a955 Mon Sep 17 00:00:00 2001
> > From: Trond Myklebust <trond.myklebust@xxxxxxxxxxxxxxx>
> > Date: Fri, 30 Jan 2015 18:12:28 -0500
> > Subject: SUNRPC: NULL utsname dereference on NFS umount during namespace cleanup
> > MIME-Version: 1.0
> > Content-Type: text/plain; charset=UTF-8
> > Content-Transfer-Encoding: 8bit
> > 
> > From: Trond Myklebust <trond.myklebust@xxxxxxxxxxxxxxx>
> > 
> > commit 03a9a42a1a7e5b3e7919ddfacc1d1cc81882a955 upstream.
> > 
> > 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@xxxxxxxxxxxx
> > Reported-by: Bruno Prémont <bonbons@xxxxxxxxxxxxxxxxx>
> > Signed-off-by: Trond Myklebust <trond.myklebust@xxxxxxxxxxxxxxx>
> > Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
> > 
> > ---
> >  fs/lockd/mon.c              |   13 +++++++++----
> >  include/linux/sunrpc/clnt.h |    3 ++-
> >  net/sunrpc/clnt.c           |   12 +++++++-----
> >  net/sunrpc/rpcb_clnt.c      |    8 ++++++--
> >  4 files changed, 24 insertions(+), 12 deletions(-)
> > 
> > --- a/fs/lockd/mon.c
> > +++ b/fs/lockd/mon.c
> > @@ -65,7 +65,7 @@ static inline struct sockaddr *nsm_addr(
> >  	return (struct sockaddr *)&nsm->sm_addr;
> >  }
> >  
> > -static struct rpc_clnt *nsm_create(struct net *net)
> > +static struct rpc_clnt *nsm_create(struct net *net, const char *nodename)
> >  {
> >  	struct sockaddr_in sin = {
> >  		.sin_family		= AF_INET,
> > @@ -77,6 +77,7 @@ static struct rpc_clnt *nsm_create(struc
> >  		.address		= (struct sockaddr *)&sin,
> >  		.addrsize		= sizeof(sin),
> >  		.servername		= "rpc.statd",
> > +		.nodename		= nodename,
> >  		.program		= &nsm_program,
> >  		.version		= NSM_VERSION,
> >  		.authflavor		= RPC_AUTH_NULL,
> > @@ -102,7 +103,7 @@ out:
> >  	return clnt;
> >  }
> >  
> > -static struct rpc_clnt *nsm_client_get(struct net *net)
> > +static struct rpc_clnt *nsm_client_get(struct net *net, const char *nodename)
> >  {
> >  	struct rpc_clnt	*clnt, *new;
> >  	struct lockd_net *ln = net_generic(net, lockd_net_id);
> > @@ -111,7 +112,7 @@ static struct rpc_clnt *nsm_client_get(s
> >  	if (clnt != NULL)
> >  		goto out;
> >  
> > -	clnt = new = nsm_create(net);
> > +	clnt = new = nsm_create(net, nodename);
> >  	if (IS_ERR(clnt))
> >  		goto out;
> >  
> > @@ -190,19 +191,23 @@ int nsm_monitor(const struct nlm_host *h
> >  	struct nsm_res	res;
> >  	int		status;
> >  	struct rpc_clnt *clnt;
> > +	const char *nodename = NULL;
> >  
> >  	dprintk("lockd: nsm_monitor(%s)\n", nsm->sm_name);
> >  
> >  	if (nsm->sm_monitored)
> >  		return 0;
> >  
> > +	if (host->h_rpcclnt)
> > +		nodename = host->h_rpcclnt->cl_nodename;
> > +
> >  	/*
> >  	 * Choose whether to record the caller_name or IP address of
> >  	 * this peer in the local rpc.statd's database.
> >  	 */
> >  	nsm->sm_mon_name = nsm_use_hostnames ? nsm->sm_name : nsm->sm_addrbuf;
> >  
> > -	clnt = nsm_client_get(host->net);
> > +	clnt = nsm_client_get(host->net, nodename);
> >  	if (IS_ERR(clnt)) {
> >  		status = PTR_ERR(clnt);
> >  		dprintk("lockd: failed to create NSM upcall transport, "
> > --- a/include/linux/sunrpc/clnt.h
> > +++ b/include/linux/sunrpc/clnt.h
> > @@ -57,7 +57,7 @@ struct rpc_clnt {
> >  	const struct rpc_timeout *cl_timeout;	/* Timeout strategy */
> >  
> >  	int			cl_nodelen;	/* nodename length */
> > -	char 			cl_nodename[UNX_MAXNODENAME];
> > +	char 			cl_nodename[UNX_MAXNODENAME+1];
> >  	struct rpc_pipe_dir_head cl_pipedir_objects;
> >  	struct rpc_clnt *	cl_parent;	/* Points to parent of clones */
> >  	struct rpc_rtt		cl_rtt_default;
> > @@ -109,6 +109,7 @@ struct rpc_create_args {
> >  	struct sockaddr		*saddress;
> >  	const struct rpc_timeout *timeout;
> >  	const char		*servername;
> > +	const char		*nodename;
> >  	const struct rpc_program *program;
> >  	u32			prognumber;	/* overrides program->number */
> >  	u32			version;
> > --- a/net/sunrpc/clnt.c
> > +++ b/net/sunrpc/clnt.c
> > @@ -286,10 +286,8 @@ static struct rpc_xprt *rpc_clnt_set_tra
> >  
> >  static void rpc_clnt_set_nodename(struct rpc_clnt *clnt, const char *nodename)
> >  {
> > -	clnt->cl_nodelen = strlen(nodename);
> > -	if (clnt->cl_nodelen > UNX_MAXNODENAME)
> > -		clnt->cl_nodelen = UNX_MAXNODENAME;
> > -	memcpy(clnt->cl_nodename, nodename, clnt->cl_nodelen);
> > +	clnt->cl_nodelen = strlcpy(clnt->cl_nodename,
> > +			nodename, sizeof(clnt->cl_nodename));
> >  }
> >  
> >  static int rpc_client_register(struct rpc_clnt *clnt,
> > @@ -360,6 +358,7 @@ static struct rpc_clnt * rpc_new_client(
> >  	const struct rpc_version *version;
> >  	struct rpc_clnt *clnt = NULL;
> >  	const struct rpc_timeout *timeout;
> > +	const char *nodename = args->nodename;
> >  	int err;
> >  
> >  	/* sanity check the name before trying to print it */
> > @@ -415,8 +414,10 @@ static struct rpc_clnt * rpc_new_client(
> >  
> >  	atomic_set(&clnt->cl_count, 1);
> >  
> > +	if (nodename == NULL)
> > +		nodename = utsname()->nodename;
> >  	/* save the nodename */
> > -	rpc_clnt_set_nodename(clnt, utsname()->nodename);
> > +	rpc_clnt_set_nodename(clnt, nodename);
> >  
> >  	err = rpc_client_register(clnt, args->authflavor, args->client_name);
> >  	if (err)
> > @@ -563,6 +564,7 @@ static struct rpc_clnt *__rpc_clone_clie
> >  	if (xprt == NULL)
> >  		goto out_err;
> >  	args->servername = xprt->servername;
> > +	args->nodename = clnt->cl_nodename;
> >  
> >  	new = rpc_new_client(args, xprt, clnt);
> >  	if (IS_ERR(new)) {
> > --- a/net/sunrpc/rpcb_clnt.c
> > +++ b/net/sunrpc/rpcb_clnt.c
> > @@ -355,7 +355,8 @@ out:
> >  	return result;
> >  }
> >  
> > -static struct rpc_clnt *rpcb_create(struct net *net, const char *hostname,
> > +static struct rpc_clnt *rpcb_create(struct net *net, const char *nodename,
> > +				    const char *hostname,
> >  				    struct sockaddr *srvaddr, size_t salen,
> >  				    int proto, u32 version)
> >  {
> > @@ -365,6 +366,7 @@ static struct rpc_clnt *rpcb_create(stru
> >  		.address	= srvaddr,
> >  		.addrsize	= salen,
> >  		.servername	= hostname,
> > +		.nodename	= nodename,
> >  		.program	= &rpcb_program,
> >  		.version	= version,
> >  		.authflavor	= RPC_AUTH_UNIX,
> > @@ -740,7 +742,9 @@ void rpcb_getport_async(struct rpc_task
> >  	dprintk("RPC: %5u %s: trying rpcbind version %u\n",
> >  		task->tk_pid, __func__, bind_version);
> >  
> > -	rpcb_clnt = rpcb_create(xprt->xprt_net, xprt->servername, sap, salen,
> > +	rpcb_clnt = rpcb_create(xprt->xprt_net,
> > +				clnt->cl_nodename,
> > +				xprt->servername, sap, salen,
> >  				xprt->prot, bind_version);
> >  	if (IS_ERR(rpcb_clnt)) {
> >  		status = PTR_ERR(rpcb_clnt);
> > 
> > 
> > Patches currently in stable-queue which might be from trond.myklebust@xxxxxxxxxxxxxxx are
> > 
> > queue-3.14/sunrpc-null-utsname-dereference-on-nfs-umount-during-namespace-cleanup.patch
> > queue-3.14/nfs-don-t-call-blocking-operations-while-task_running.patch
> > queue-3.14/nfsv4.1-fix-a-kfree-of-uninitialised-pointers-in-decode_cb_sequence_args.patch
> > --
> > To unsubscribe from this list: send the line "unsubscribe stable" in
> > the body of a message to majordomo@xxxxxxxxxxxxxxx
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]