]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
nfsd: avoid a NULL dereference in __cld_pipe_upcall()
authorScott Mayhew <smayhew@redhat.com>
Fri, 10 Jul 2020 20:33:07 +0000 (16:33 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 19 Aug 2020 06:24:09 +0000 (08:24 +0200)
[ 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

index a8fb18609146a2a07cd63d652e98770431ba76e6..82679990dd9b4b060286555bfd6f4cbae344297b 100644 (file)
@@ -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 @@ out:
 }
 
 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)