syzbot reported: BUG: KASAN: null-ptr-deref in instrument_atomic_read include/linux/instrumented.h:82 [inline] BUG: KASAN: null-ptr-deref in _test_bit include/asm-generic/bitops/instrumented-non-atomic.h:141 [inline] BUG: KASAN: null-ptr-deref in xprt_throttle_congested net/sunrpc/xprt.c:1708 [inline] BUG: KASAN: null-ptr-deref in xprt_reserve+0xe2/0x2c0 net/sunrpc/xprt.c:1948 Read of size 8 at addr 0000000000000628 by task syz.8.3118/20390 Call Trace: dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120 kasan_report+0x117/0x150 mm/kasan/report.c:595 check_region_inline mm/kasan/generic.c:-1 [inline] kasan_check_range+0x264/0x2c0 mm/kasan/generic.c:200 instrument_atomic_read include/linux/instrumented.h:82 [inline] _test_bit include/asm-generic/bitops/instrumented-non-atomic.h:141 [inline] xprt_throttle_congested net/sunrpc/xprt.c:1708 [inline] xprt_reserve+0xe2/0x2c0 net/sunrpc/xprt.c:1948 __rpc_execute+0x526/0x1280 net/sunrpc/sched.c:947 rpc_execute+0x1c1/0x390 net/sunrpc/sched.c:1023 rpc_run_task+0x4a6/0x660 net/sunrpc/clnt.c:1269 rpc_ping_noreply net/sunrpc/clnt.c:2944 [inline] rpc_create_xprt+0x452/0xa90 net/sunrpc/clnt.c:494 rpc_create+0x649/0x900 net/sunrpc/clnt.c:619 gssp_rpc_create net/sunrpc/auth_gss/gss_rpc_upcall.c:107 [inline] set_gssp_clnt+0x188/0x2d0 net/sunrpc/auth_gss/gss_rpc_upcall.c:131 write_gssp+0x21e/0x310 net/sunrpc/auth_gss/svcauth_gss.c:1423 pde_write fs/proc/inode.c:330 [inline] proc_reg_write+0x1e9/0x2e0 fs/proc/inode.c:342 vfs_write+0x296/0xba0 fs/read_write.c:685 ksys_write+0x150/0x270 fs/read_write.c:739 do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline] do_syscall_64+0x166/0x520 arch/x86/entry/syscall_64.c:84 entry_SYSCALL_64_after_hwframe+0x77/0x7f The GSS proxy client setup races with sysfs. xprt_switch_alloc() publishes the transport in sysfs before rpc_new_client() sets xprt->main = true. The sysfs offline handler rejects writes when main is already true, so userspace can set XPRT_OFFLINE in that window. The initial RPC then runs with the only transport offline. xprt_is_active() only rejects a transport whose refcount is zero or whose XPRT_OFFLINE bit is set, and a transport that is still on the switch's list always holds a reference. xprt_switch_find_first_entry() returns NULL, rpc_task_get_next_xprt() returns NULL with it, and since rpc_task_set_transport() returns void, the task continues with tk_xprt == NULL until xprt_reserve() dereferences it. Mark the first transport as main in xprt_switch_alloc() before creating the sysfs entries, and drop the assignment from rpc_new_client(). Fixes: e091853ebdb4 ("SUNRPC mark the first transport") Reported-by: syzbot+ae55a0fac80c73c938ac@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=ae55a0fac80c73c938ac Signed-off-by: Drif Abdelmalek Mohamed Said --- net/sunrpc/clnt.c | 1 - net/sunrpc/xprtmultipath.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 6cedc824cf82..aa9f9c185c02 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -419,7 +419,6 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, } rpc_clnt_set_transport(clnt, xprt, timeout); - xprt->main = true; xprt_iter_init(&clnt->cl_xpi, xps); xprt_switch_put(xps); diff --git a/net/sunrpc/xprtmultipath.c b/net/sunrpc/xprtmultipath.c index 3ba818d637be..5e2d43d6c643 100644 --- a/net/sunrpc/xprtmultipath.c +++ b/net/sunrpc/xprtmultipath.c @@ -159,6 +159,7 @@ struct rpc_xprt_switch *xprt_switch_alloc(struct rpc_xprt *xprt, atomic_long_set(&xps->xps_queuelen, 0); xps->xps_net = NULL; INIT_LIST_HEAD(&xps->xps_xprt_list); + xprt->main = true; xps->xps_iter_ops = &rpc_xprt_iter_singular; rpc_sysfs_xprt_switch_setup(xps, xprt, gfp_flags); xprt_switch_add_xprt_locked(xps, xprt); -- 2.43.0