Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fb334059 authored by Marcel Holtmann's avatar Marcel Holtmann Committed by Gustavo Padovan
Browse files

Bluetooth: Restrict to one SCO listening socket



The SCO sockets are only identified by its address. So only allow one
SCO socket in listening state per address or BDADDR_ANY.

Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
Signed-off-by: default avatarGustavo Padovan <gustavo@padovan.org>
parent 8ed21f7e
Loading
Loading
Loading
Loading
+22 −7
Original line number Original line Diff line number Diff line
@@ -273,19 +273,22 @@ static inline void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb)
}
}


/* -------- Socket interface ---------- */
/* -------- Socket interface ---------- */
static struct sock *__sco_get_sock_by_addr(bdaddr_t *ba)
static struct sock *__sco_get_sock_listen_by_addr(bdaddr_t *ba)
{
{
	struct sock *sk;
	struct hlist_node *node;
	struct hlist_node *node;
	struct sock *sk;

	sk_for_each(sk, node, &sco_sk_list.head) {
		if (sk->sk_state != BT_LISTEN)
			continue;


	sk_for_each(sk, node, &sco_sk_list.head)
		if (!bacmp(&bt_sk(sk)->src, ba))
		if (!bacmp(&bt_sk(sk)->src, ba))
			goto found;
	sk = NULL;
found:
			return sk;
			return sk;
	}
	}


	return NULL;
}

/* Find socket listening on source bdaddr.
/* Find socket listening on source bdaddr.
 * Returns closest match.
 * Returns closest match.
 */
 */
@@ -529,6 +532,7 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen
static int sco_sock_listen(struct socket *sock, int backlog)
static int sco_sock_listen(struct socket *sock, int backlog)
{
{
	struct sock *sk = sock->sk;
	struct sock *sk = sock->sk;
	bdaddr_t *src = &bt_sk(sk)->src;
	int err = 0;
	int err = 0;


	BT_DBG("sk %p backlog %d", sk, backlog);
	BT_DBG("sk %p backlog %d", sk, backlog);
@@ -545,10 +549,21 @@ static int sco_sock_listen(struct socket *sock, int backlog)
		goto done;
		goto done;
	}
	}


	write_lock(&sco_sk_list.lock);

	if (__sco_get_sock_listen_by_addr(src)) {
		err = -EADDRINUSE;
		goto unlock;
	}

	sk->sk_max_ack_backlog = backlog;
	sk->sk_max_ack_backlog = backlog;
	sk->sk_ack_backlog = 0;
	sk->sk_ack_backlog = 0;

	sk->sk_state = BT_LISTEN;
	sk->sk_state = BT_LISTEN;


unlock:
	write_unlock(&sco_sk_list.lock);

done:
done:
	release_sock(sk);
	release_sock(sk);
	return err;
	return err;