smc_clcsock_user_data() can return NULL when the listening SMC socket is
being torn down concurrently. During close, smc_close_active() sets
sk_user_data to NULL on the underlying CLC socket before shutting it
down. If a TCP SYN completion arrives in this window,
smc_tcp_syn_recv_sock() is called from softirq and dereferences the NULL
pointer when accessing smc->queued_smc_hs.
The sibling function smc_hs_congested() already handles this case by
checking for NULL and returning early. Add the same NULL check to
smc_tcp_syn_recv_sock().
BUG: KASAN: null-ptr-deref in smc_tcp_syn_recv_sock (arch/x86/include/asm/atomic.h:23 include/linux/atomic/atomic-arch-fallback.h:457 include/linux/atomic/atomic-instrumented.h:33 net/smc/af_smc.c:136)
Read of size 4 at addr 00000000000006b0 by task poc-F362/154
CPU: 2 UID: 0 PID: 154 Comm: poc-F362 Not tainted 7.0.0-rc3 #1 PREEMPT(lazy)
Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
Call Trace:
<IRQ>
dump_stack_lvl (lib/dump_stack.c:122)
kasan_report (mm/kasan/report.c:597)
? smc_tcp_syn_recv_sock (arch/x86/include/asm/atomic.h:23 include/linux/atomic/atomic-arch-fallback.h:457 include/linux/atomic/atomic-instrumented.h:33 net/smc/af_smc.c:136)
? smc_tcp_syn_recv_sock (arch/x86/include/asm/atomic.h:23 include/linux/atomic/atomic-arch-fallback.h:457 include/linux/atomic/atomic-instrumented.h:33 net/smc/af_smc.c:136)
kasan_check_range (mm/kasan/generic.c:186 (discriminator 1) mm/kasan/generic.c:200 (discriminator 1))
smc_tcp_syn_recv_sock (arch/x86/include/asm/atomic.h:23 include/linux/atomic/atomic-arch-fallback.h:457 include/linux/atomic/atomic-instrumented.h:33 net/smc/af_smc.c:136)
tcp_check_req (net/ipv4/tcp_minisocks.c:927)
tcp_v4_rcv (net/ipv4/tcp_ipv4.c:2245)
ip_protocol_deliver_rcu (net/ipv4/ip_input.c:209)
ip_local_deliver_finish (include/linux/rcupdate.h:883 net/ipv4/ip_input.c:242)
ip_local_deliver (net/ipv4/ip_input.c:259)
ip_rcv (net/ipv4/ip_input.c:573)
__netif_receive_skb_one_core (net/core/dev.c:6164)
Fixes: 8270d9c21041 ("net/smc: Limit backlog connections")
Cc: stable@vger.kernel.org
Signed-off-by: Mehul Rao <redacted>
---
net/smc/af_smc.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index d0119afcc6a1..bb8966eeb332 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -132,6 +132,8 @@ static struct sock *smc_tcp_syn_recv_sock(const struct sock *sk,
struct sock *child;
smc = smc_clcsock_user_data(sk);
+ if (!smc)
+ goto drop;
if (READ_ONCE(sk->sk_ack_backlog) + atomic_read(&smc->queued_smc_hs) >
sk->sk_max_ack_backlog)
--
2.53.0