Commit cbdeaee9 authored by Zhang Xiaoxu's avatar Zhang Xiaoxu Committed by Anna Schumaker

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: 2a338a54 ("sunrpc: add a symlink from rpc-client directory to the xprt_switch")
Fixes: d408ebe0 ("sunrpc: add add sysfs directory per xprt under each xprt_switch")
Fixes: baea9944 ("sunrpc: add xprt_switch direcotry to sunrpc's sysfs")
Signed-off-by: default avatarZhang Xiaoxu <zhangxiaoxu5@huawei.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent e59679f2
...@@ -518,13 +518,16 @@ void rpc_sysfs_client_setup(struct rpc_clnt *clnt, ...@@ -518,13 +518,16 @@ void rpc_sysfs_client_setup(struct rpc_clnt *clnt,
struct net *net) struct net *net)
{ {
struct rpc_sysfs_client *rpc_client; 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, rpc_client = rpc_sysfs_client_alloc(rpc_sunrpc_client_kobj,
net, clnt->cl_clid); net, clnt->cl_clid);
if (rpc_client) { if (rpc_client) {
char name[] = "switch"; char name[] = "switch";
struct rpc_sysfs_xprt_switch *xswitch =
(struct rpc_sysfs_xprt_switch *)xprt_switch->xps_sysfs;
int ret; int ret;
clnt->cl_sysfs = rpc_client; clnt->cl_sysfs = rpc_client;
...@@ -558,6 +561,8 @@ void rpc_sysfs_xprt_switch_setup(struct rpc_xprt_switch *xprt_switch, ...@@ -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_switch = xprt_switch;
rpc_xprt_switch->xprt = xprt; rpc_xprt_switch->xprt = xprt;
kobject_uevent(&rpc_xprt_switch->kobject, KOBJ_ADD); 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, ...@@ -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 *switch_obj =
(struct rpc_sysfs_xprt_switch *)xprt_switch->xps_sysfs; (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); rpc_xprt = rpc_sysfs_xprt_alloc(&switch_obj->kobject, xprt, gfp_flags);
if (rpc_xprt) { if (rpc_xprt) {
xprt->xprt_sysfs = rpc_xprt; xprt->xprt_sysfs = rpc_xprt;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment