diff options
author | Zhang Xiaoxu <zhangxiaoxu5@huawei.com> | 2022-10-20 06:42:17 +0300 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2022-10-27 22:52:10 +0300 |
commit | cbdeaee94a415800c65a8c3fa04d9664a8b8fb3a (patch) | |
tree | b8ad1da410c786f7169690bb1efd909d22372980 | |
parent | e59679f2b7e522ecad99974e5636291ffd47c184 (diff) | |
download | linux-cbdeaee94a415800c65a8c3fa04d9664a8b8fb3a.tar.xz |
SUNRPC: Fix null-ptr-deref when xps sysfs alloc failed
There is a null-ptr-deref when xps sysfs alloc failed:
BUG: KASAN: null-ptr-deref in sysfs_do_create_link_sd+0x40/0xd0
Read of size 8 at addr 0000000000000030 by task gssproxy/457
CPU: 5 PID: 457 Comm: gssproxy Not tainted 6.0.0-09040-g02357b27ee03 #9
Call Trace:
<TASK>
dump_stack_lvl+0x34/0x44
kasan_report+0xa3/0x120
sysfs_do_create_link_sd+0x40/0xd0
rpc_sysfs_client_setup+0x161/0x1b0
rpc_new_client+0x3fc/0x6e0
rpc_create_xprt+0x71/0x220
rpc_create+0x1d4/0x350
gssp_rpc_create+0xc3/0x160
set_gssp_clnt+0xbc/0x140
write_gssp+0x116/0x1a0
proc_reg_write+0xd6/0x130
vfs_write+0x177/0x690
ksys_write+0xb9/0x150
do_syscall_64+0x35/0x80
entry_SYSCALL_64_after_hwframe+0x46/0xb0
When the xprt_switch sysfs alloc failed, should not add xprt and
switch sysfs to it, otherwise, maybe null-ptr-deref; also initialize
the 'xps_sysfs' to NULL to avoid oops when destroy it.
Fixes: 2a338a543163 ("sunrpc: add a symlink from rpc-client directory to the xprt_switch")
Fixes: d408ebe04ac5 ("sunrpc: add add sysfs directory per xprt under each xprt_switch")
Fixes: baea99445dd4 ("sunrpc: add xprt_switch direcotry to sunrpc's sysfs")
Signed-off-by: Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
-rw-r--r-- | net/sunrpc/sysfs.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/net/sunrpc/sysfs.c b/net/sunrpc/sysfs.c index c65c90ad626a..c1f559892ae8 100644 --- a/net/sunrpc/sysfs.c +++ b/net/sunrpc/sysfs.c @@ -518,13 +518,16 @@ void rpc_sysfs_client_setup(struct rpc_clnt *clnt, struct net *net) { struct rpc_sysfs_client *rpc_client; + struct rpc_sysfs_xprt_switch *xswitch = + (struct rpc_sysfs_xprt_switch *)xprt_switch->xps_sysfs; + + if (!xswitch) + return; rpc_client = rpc_sysfs_client_alloc(rpc_sunrpc_client_kobj, net, clnt->cl_clid); if (rpc_client) { char name[] = "switch"; - struct rpc_sysfs_xprt_switch *xswitch = - (struct rpc_sysfs_xprt_switch *)xprt_switch->xps_sysfs; int ret; clnt->cl_sysfs = rpc_client; @@ -558,6 +561,8 @@ void rpc_sysfs_xprt_switch_setup(struct rpc_xprt_switch *xprt_switch, rpc_xprt_switch->xprt_switch = xprt_switch; rpc_xprt_switch->xprt = xprt; kobject_uevent(&rpc_xprt_switch->kobject, KOBJ_ADD); + } else { + xprt_switch->xps_sysfs = NULL; } } @@ -569,6 +574,9 @@ void rpc_sysfs_xprt_setup(struct rpc_xprt_switch *xprt_switch, struct rpc_sysfs_xprt_switch *switch_obj = (struct rpc_sysfs_xprt_switch *)xprt_switch->xps_sysfs; + if (!switch_obj) + return; + rpc_xprt = rpc_sysfs_xprt_alloc(&switch_obj->kobject, xprt, gfp_flags); if (rpc_xprt) { xprt->xprt_sysfs = rpc_xprt; |