Message ID | 20210830172137.325718-1-eric.dumazet@gmail.com |
---|---|
State | New |
Headers | show |
Series | [net-next] af_unix: fix potential NULL deref in unix_dgram_connect() | expand |
Hello: This patch was applied to netdev/net-next.git (refs/heads/master): On Mon, 30 Aug 2021 10:21:37 -0700 you wrote: > From: Eric Dumazet <edumazet@google.com> > > syzbot was able to trigger NULL deref in unix_dgram_connect() [1] > > This happens in > > if (unix_peer(sk)) > sk->sk_state = other->sk_state = TCP_ESTABLISHED; // crash because @other is NULL > > [...] Here is the summary with links: - [net-next] af_unix: fix potential NULL deref in unix_dgram_connect() https://git.kernel.org/netdev/net-next/c/dc56ad7028c5 You are awesome, thank you! -- Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html
On Mon, Aug 30, 2021 at 10:21 AM Eric Dumazet <eric.dumazet@gmail.com> wrote: > @@ -1805,6 +1807,7 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, > > unix_state_unlock(sk); > > + sk->sk_state = TCP_CLOSE; Does this need to be moved before the unix_state_unlock()? The rest looks good to me. Thanks.
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 4cf0b1c47f0f99e99c12d37af2494f301a965856..5d49c92a2487d663d511d26c2cb024f5f3d670d8 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -494,7 +494,7 @@ static void unix_dgram_disconnected(struct sock *sk, struct sock *other) sk_error_report(other); } } - sk->sk_state = other->sk_state = TCP_CLOSE; + other->sk_state = TCP_CLOSE; } static void unix_sock_destructor(struct sock *sk) @@ -1196,6 +1196,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr, if (err) goto out_unlock; + sk->sk_state = other->sk_state = TCP_ESTABLISHED; } else { /* * 1003.1g breaking connected state with AF_UNSPEC @@ -1209,7 +1210,10 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr, */ if (unix_peer(sk)) { struct sock *old_peer = unix_peer(sk); + unix_peer(sk) = other; + if (!other) + sk->sk_state = TCP_CLOSE; unix_dgram_peer_wake_disconnect_wakeup(sk, old_peer); unix_state_double_unlock(sk, other); @@ -1222,8 +1226,6 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr, unix_state_double_unlock(sk, other); } - if (unix_peer(sk)) - sk->sk_state = other->sk_state = TCP_ESTABLISHED; return 0; out_unlock: @@ -1805,6 +1807,7 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, unix_state_unlock(sk); + sk->sk_state = TCP_CLOSE; unix_dgram_disconnected(sk, other); sock_put(other); err = -ECONNREFUSED;