Commit e1dee2c1 authored by Desmond Cheong Zhi Xi's avatar Desmond Cheong Zhi Xi Committed by Luiz Augusto von Dentz

Bluetooth: fix repeated calls to sco_sock_kill

In commit 4e1a720d ("Bluetooth: avoid killing an already killed
socket"), a check was added to sco_sock_kill to skip killing a socket
if the SOCK_DEAD flag was set.

This was done after a trace for a use-after-free bug showed that the
same sock pointer was being killed twice.

Unfortunately, this check prevents sco_sock_kill from running on any
socket. sco_sock_kill kills a socket only if it's zapped and orphaned,
however sock_orphan announces that the socket is dead before detaching
it. i.e., orphaned sockets have the SOCK_DEAD flag set.

To fix this, we remove the check for SOCK_DEAD, and avoid repeated
calls to sco_sock_kill by removing incorrect calls in:

1. sco_sock_timeout. The socket should not be killed on timeout as
further processing is expected to be done. For example,
sco_sock_connect sets the timer then waits for the socket to be
connected or for an error to be returned.

2. sco_conn_del. This function should clean up resources for the
connection, but the socket itself should be cleaned up in
sco_sock_release.

3. sco_sock_close. Calls to sco_sock_close in sco_sock_cleanup_listen
and sco_sock_release are followed by sco_sock_kill. Hence the
duplicated call should be removed.

Fixes: 4e1a720d ("Bluetooth: avoid killing an already killed socket")
Signed-off-by: default avatarDesmond Cheong Zhi Xi <desmondcheongzx@gmail.com>
Signed-off-by: default avatarLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
parent b7ce436a
...@@ -97,8 +97,6 @@ static void sco_sock_timeout(struct work_struct *work) ...@@ -97,8 +97,6 @@ static void sco_sock_timeout(struct work_struct *work)
sk->sk_err = ETIMEDOUT; sk->sk_err = ETIMEDOUT;
sk->sk_state_change(sk); sk->sk_state_change(sk);
release_sock(sk); release_sock(sk);
sco_sock_kill(sk);
sock_put(sk); sock_put(sk);
} }
...@@ -197,7 +195,6 @@ static void sco_conn_del(struct hci_conn *hcon, int err) ...@@ -197,7 +195,6 @@ static void sco_conn_del(struct hci_conn *hcon, int err)
sco_sock_clear_timer(sk); sco_sock_clear_timer(sk);
sco_chan_del(sk, err); sco_chan_del(sk, err);
release_sock(sk); release_sock(sk);
sco_sock_kill(sk);
sock_put(sk); sock_put(sk);
/* Ensure no more work items will run before freeing conn. */ /* Ensure no more work items will run before freeing conn. */
...@@ -404,8 +401,7 @@ static void sco_sock_cleanup_listen(struct sock *parent) ...@@ -404,8 +401,7 @@ static void sco_sock_cleanup_listen(struct sock *parent)
*/ */
static void sco_sock_kill(struct sock *sk) static void sco_sock_kill(struct sock *sk)
{ {
if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket || if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
sock_flag(sk, SOCK_DEAD))
return; return;
BT_DBG("sk %p state %d", sk, sk->sk_state); BT_DBG("sk %p state %d", sk, sk->sk_state);
...@@ -457,7 +453,6 @@ static void sco_sock_close(struct sock *sk) ...@@ -457,7 +453,6 @@ static void sco_sock_close(struct sock *sk)
sco_sock_clear_timer(sk); sco_sock_clear_timer(sk);
__sco_sock_close(sk); __sco_sock_close(sk);
release_sock(sk); release_sock(sk);
sco_sock_kill(sk);
} }
static void sco_skb_put_cmsg(struct sk_buff *skb, struct msghdr *msg, static void sco_skb_put_cmsg(struct sk_buff *skb, struct msghdr *msg,
......
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