Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

nfsd: avoid a NULL dereference in __cld_pipe_upcall()

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>

authored by

Scott Mayhew and committed by
Chuck Lever
df60446c 94415b06

+11 -13
+11 -13
fs/nfsd/nfs4recover.c
··· 747 747 }; 748 748 749 749 static int 750 - __cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg) 750 + __cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg, struct nfsd_net *nn) 751 751 { 752 752 int ret; 753 753 struct rpc_pipe_msg msg; 754 754 struct cld_upcall *cup = container_of(cmsg, struct cld_upcall, cu_u); 755 - struct nfsd_net *nn = net_generic(pipe->dentry->d_sb->s_fs_info, 756 - nfsd_net_id); 757 755 758 756 memset(&msg, 0, sizeof(msg)); 759 757 msg.data = cmsg; ··· 771 773 } 772 774 773 775 static int 774 - cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg) 776 + cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg, struct nfsd_net *nn) 775 777 { 776 778 int ret; 777 779 ··· 780 782 * upcalls queued. 781 783 */ 782 784 do { 783 - ret = __cld_pipe_upcall(pipe, cmsg); 785 + ret = __cld_pipe_upcall(pipe, cmsg, nn); 784 786 } while (ret == -EAGAIN); 785 787 786 788 return ret; ··· 1113 1115 memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data, 1114 1116 clp->cl_name.len); 1115 1117 1116 - ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg); 1118 + ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn); 1117 1119 if (!ret) { 1118 1120 ret = cup->cu_u.cu_msg.cm_status; 1119 1121 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); ··· 1178 1180 } else 1179 1181 cmsg->cm_u.cm_clntinfo.cc_princhash.cp_len = 0; 1180 1182 1181 - ret = cld_pipe_upcall(cn->cn_pipe, cmsg); 1183 + ret = cld_pipe_upcall(cn->cn_pipe, cmsg, nn); 1182 1184 if (!ret) { 1183 1185 ret = cmsg->cm_status; 1184 1186 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); ··· 1216 1218 memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data, 1217 1219 clp->cl_name.len); 1218 1220 1219 - ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg); 1221 + ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn); 1220 1222 if (!ret) { 1221 1223 ret = cup->cu_u.cu_msg.cm_status; 1222 1224 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); ··· 1259 1261 memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data, 1260 1262 clp->cl_name.len); 1261 1263 1262 - ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg); 1264 + ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn); 1263 1265 if (!ret) { 1264 1266 ret = cup->cu_u.cu_msg.cm_status; 1265 1267 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); ··· 1402 1404 } 1403 1405 1404 1406 cup->cu_u.cu_msg.cm_cmd = Cld_GraceStart; 1405 - ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg); 1407 + ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn); 1406 1408 if (!ret) 1407 1409 ret = cup->cu_u.cu_msg.cm_status; 1408 1410 ··· 1430 1432 1431 1433 cup->cu_u.cu_msg.cm_cmd = Cld_GraceDone; 1432 1434 cup->cu_u.cu_msg.cm_u.cm_gracetime = nn->boot_time; 1433 - ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg); 1435 + ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn); 1434 1436 if (!ret) 1435 1437 ret = cup->cu_u.cu_msg.cm_status; 1436 1438 ··· 1458 1460 } 1459 1461 1460 1462 cup->cu_u.cu_msg.cm_cmd = Cld_GraceDone; 1461 - ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg); 1463 + ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn); 1462 1464 if (!ret) 1463 1465 ret = cup->cu_u.cu_msg.cm_status; 1464 1466 ··· 1522 1524 goto out_err; 1523 1525 } 1524 1526 cup->cu_u.cu_msg.cm_cmd = Cld_GetVersion; 1525 - ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg); 1527 + ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn); 1526 1528 if (!ret) { 1527 1529 ret = cup->cu_u.cu_msg.cm_status; 1528 1530 if (ret)