Re: [PATCH] nfsd: avoid a NULL dereference in __cld_pipe_upcall()

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

 



Hi Scott-

> On Jul 10, 2020, at 4:33 PM, Scott Mayhew <smayhew@xxxxxxxxxx> wrote:
> 
> If the rpc_pipefs is unmounted, then the rpc_pipe->dentry becomes NULL
> and dereferencing the dentry->d_sb will trigger an oops.  The only
> reason we're doing that is to determine the nfsd_net, which could
> instead be passed in by the caller.  So do that instead.
> 
> Signed-off-by: Scott Mayhew <smayhew@xxxxxxxxxx>

Looks straightforward. Applied to the nfsd-5.9 testing tree.

I'm wondering about automatic backports to stable. This fix does not
apply to kernels before v5.6, but IIUC addresses a crash introduced
in f3f8014862d8 ("nfsd: add the infrastructure to handle the cld upcall")
[2012] ?

Is "Cc: <stable@xxxxxxxxxx> # v5.6+" appropriate?

Also, is there a bug report that documents the crash?


> ---
> fs/nfsd/nfs4recover.c | 24 +++++++++++-------------
> 1 file changed, 11 insertions(+), 13 deletions(-)
> 
> diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
> index 9e40dfecf1b1..186fa2c2c6ba 100644
> --- a/fs/nfsd/nfs4recover.c
> +++ b/fs/nfsd/nfs4recover.c
> @@ -747,13 +747,11 @@ struct cld_upcall {
> };
> 
> static int
> -__cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg)
> +__cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg, struct nfsd_net *nn)
> {
> 	int ret;
> 	struct rpc_pipe_msg msg;
> 	struct cld_upcall *cup = container_of(cmsg, struct cld_upcall, cu_u);
> -	struct nfsd_net *nn = net_generic(pipe->dentry->d_sb->s_fs_info,
> -					  nfsd_net_id);
> 
> 	memset(&msg, 0, sizeof(msg));
> 	msg.data = cmsg;
> @@ -773,7 +771,7 @@ __cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg)
> }
> 
> static int
> -cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg)
> +cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg, struct nfsd_net *nn)
> {
> 	int ret;
> 
> @@ -782,7 +780,7 @@ cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg)
> 	 *  upcalls queued.
> 	 */
> 	do {
> -		ret = __cld_pipe_upcall(pipe, cmsg);
> +		ret = __cld_pipe_upcall(pipe, cmsg, nn);
> 	} while (ret == -EAGAIN);
> 
> 	return ret;
> @@ -1115,7 +1113,7 @@ nfsd4_cld_create(struct nfs4_client *clp)
> 	memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
> 			clp->cl_name.len);
> 
> -	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg);
> +	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
> 	if (!ret) {
> 		ret = cup->cu_u.cu_msg.cm_status;
> 		set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
> @@ -1180,7 +1178,7 @@ nfsd4_cld_create_v2(struct nfs4_client *clp)
> 	} else
> 		cmsg->cm_u.cm_clntinfo.cc_princhash.cp_len = 0;
> 
> -	ret = cld_pipe_upcall(cn->cn_pipe, cmsg);
> +	ret = cld_pipe_upcall(cn->cn_pipe, cmsg, nn);
> 	if (!ret) {
> 		ret = cmsg->cm_status;
> 		set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
> @@ -1218,7 +1216,7 @@ nfsd4_cld_remove(struct nfs4_client *clp)
> 	memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
> 			clp->cl_name.len);
> 
> -	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg);
> +	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
> 	if (!ret) {
> 		ret = cup->cu_u.cu_msg.cm_status;
> 		clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
> @@ -1261,7 +1259,7 @@ nfsd4_cld_check_v0(struct nfs4_client *clp)
> 	memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
> 			clp->cl_name.len);
> 
> -	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg);
> +	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
> 	if (!ret) {
> 		ret = cup->cu_u.cu_msg.cm_status;
> 		set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
> @@ -1404,7 +1402,7 @@ nfsd4_cld_grace_start(struct nfsd_net *nn)
> 	}
> 
> 	cup->cu_u.cu_msg.cm_cmd = Cld_GraceStart;
> -	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg);
> +	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
> 	if (!ret)
> 		ret = cup->cu_u.cu_msg.cm_status;
> 
> @@ -1432,7 +1430,7 @@ nfsd4_cld_grace_done_v0(struct nfsd_net *nn)
> 
> 	cup->cu_u.cu_msg.cm_cmd = Cld_GraceDone;
> 	cup->cu_u.cu_msg.cm_u.cm_gracetime = nn->boot_time;
> -	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg);
> +	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
> 	if (!ret)
> 		ret = cup->cu_u.cu_msg.cm_status;
> 
> @@ -1460,7 +1458,7 @@ nfsd4_cld_grace_done(struct nfsd_net *nn)
> 	}
> 
> 	cup->cu_u.cu_msg.cm_cmd = Cld_GraceDone;
> -	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg);
> +	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
> 	if (!ret)
> 		ret = cup->cu_u.cu_msg.cm_status;
> 
> @@ -1524,7 +1522,7 @@ nfsd4_cld_get_version(struct nfsd_net *nn)
> 		goto out_err;
> 	}
> 	cup->cu_u.cu_msg.cm_cmd = Cld_GetVersion;
> -	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg);
> +	ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
> 	if (!ret) {
> 		ret = cup->cu_u.cu_msg.cm_status;
> 		if (ret)
> -- 
> 2.25.4
> 

--
Chuck Lever






[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux