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 <[email protected]> know about it.
>

Maybe this is actually applicable to the 3.14 kernel, but it was
tagged for stable 3.18.  Trond?  Bruno?

Cheers,
--
Luís

> 
> From 03a9a42a1a7e5b3e7919ddfacc1d1cc81882a955 Mon Sep 17 00:00:00 2001
> From: Trond Myklebust <[email protected]>
> 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 <[email protected]>
> 
> 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/[email protected]
> Reported-by: Bruno Prémont <[email protected]>
> Signed-off-by: Trond Myklebust <[email protected]>
> Signed-off-by: Greg Kroah-Hartman <[email protected]>
> 
> ---
>  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 
> [email protected] 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 [email protected]
> 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 [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to