diff options
author | Mark Salyzyn <salyzyn@google.com> | 2015-05-21 09:25:02 -0700 |
---|---|---|
committer | Mark Salyzyn <salyzyn@google.com> | 2015-05-27 09:01:46 -0700 |
commit | 93e24e14287b1afa6b68136724cf37547301f282 (patch) | |
tree | 1ce46f61cce7c47a3be844e720f803a908eeb605 | |
parent | 8ad47acc40b2fce1a4d381b7459bf5cb54f9057b (diff) |
net/unix: sk_socket can disappear when state is unlocked
got a rare NULL pointer dereference in clear_bit
Signed-off-by: Mark Salyzyn <salyzyn@google.com>
Bug: 21252747
Change-Id: I27e70f2543034097c8a590a212c2c6fa846fe696
-rw-r--r-- | net/caif/caif_socket.c | 8 | ||||
-rw-r--r-- | net/unix/af_unix.c | 8 |
2 files changed, 16 insertions, 0 deletions
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index d6be3edb7a43..0b614acbf1de 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c @@ -332,6 +332,10 @@ static long caif_stream_data_wait(struct sock *sk, long timeo) release_sock(sk); timeo = schedule_timeout(timeo); lock_sock(sk); + + if (sock_flag(sk, SOCK_DEAD)) + break; + clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); } @@ -376,6 +380,10 @@ static int caif_stream_recvmsg(struct kiocb *iocb, struct socket *sock, struct sk_buff *skb; lock_sock(sk); + if (sock_flag(sk, SOCK_DEAD)) { + err = -ECONNRESET; + goto unlock; + } skb = skb_dequeue(&sk->sk_receive_queue); caif_check_flow_release(sk); diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 94404f19f9de..ce8bb5fef3f4 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1893,6 +1893,10 @@ static long unix_stream_data_wait(struct sock *sk, long timeo, unix_state_unlock(sk); timeo = freezable_schedule_timeout(timeo); unix_state_lock(sk); + + if (sock_flag(sk, SOCK_DEAD)) + break; + clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); } @@ -1957,6 +1961,10 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, struct sk_buff *skb, *last; unix_state_lock(sk); + if (sock_flag(sg, SOCK_DEAD)) { + err = -ECONNRESET; + goto unlock; + } last = skb = skb_peek(&sk->sk_receive_queue); again: if (skb == NULL) { |