| From 82b09f49762263e7cb940b3e7e249e7165acc349 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 10 Jul 2020 16:33:07 -0400 |
| Subject: nfsd: avoid a NULL dereference in __cld_pipe_upcall() |
| |
| From: Scott Mayhew <smayhew@redhat.com> |
| |
| [ Upstream commit df60446cd1fb487becd1f36f4c0da9e0e523c0cf ] |
| |
| 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. |
| |
| Fixes: 11a60d159259 ("nfsd: add a "GetVersion" upcall for nfsdcld") |
| Signed-off-by: Scott Mayhew <smayhew@redhat.com> |
| Signed-off-by: Chuck Lever <chuck.lever@oracle.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| 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 a8fb18609146a..82679990dd9b4 100644 |
| --- a/fs/nfsd/nfs4recover.c |
| +++ b/fs/nfsd/nfs4recover.c |
| @@ -755,13 +755,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; |
| @@ -781,7 +779,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; |
| |
| @@ -790,7 +788,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; |
| @@ -1123,7 +1121,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); |
| @@ -1191,7 +1189,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); |
| @@ -1229,7 +1227,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); |
| @@ -1272,7 +1270,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); |
| @@ -1418,7 +1416,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; |
| |
| @@ -1446,7 +1444,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; |
| |
| @@ -1474,7 +1472,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; |
| |
| @@ -1538,7 +1536,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.1 |
| |