aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/sco.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bluetooth/sco.c')
-rw-r--r--net/bluetooth/sco.c71
1 files changed, 27 insertions, 44 deletions
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index ac4631d..2e80aee 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -41,6 +41,7 @@
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/list.h>
+#include <linux/security.h>
#include <net/sock.h>
#include <asm/system.h>
@@ -177,7 +178,6 @@ static int sco_connect(struct sock *sk)
{
bdaddr_t *src = &bt_sk(sk)->src;
bdaddr_t *dst = &bt_sk(sk)->dst;
- __u16 pkt_type = sco_pi(sk)->pkt_type;
struct sco_conn *conn;
struct hci_conn *hcon;
struct hci_dev *hdev;
@@ -193,12 +193,10 @@ static int sco_connect(struct sock *sk)
if (lmp_esco_capable(hdev) && !disable_esco)
type = ESCO_LINK;
- else {
+ else
type = SCO_LINK;
- pkt_type &= SCO_ESCO_MASK;
- }
- hcon = hci_connect(hdev, type, pkt_type, dst, BT_SECURITY_LOW, HCI_AT_NO_BONDING);
+ hcon = hci_connect(hdev, type, dst, BT_SECURITY_LOW, HCI_AT_NO_BONDING);
if (IS_ERR(hcon)) {
err = PTR_ERR(hcon);
goto done;
@@ -381,7 +379,6 @@ static void __sco_sock_close(struct sock *sk)
sco_chan_del(sk, ECONNRESET);
break;
- case BT_CONNECT2:
case BT_CONNECT:
case BT_DISCONN:
sco_chan_del(sk, ECONNRESET);
@@ -407,8 +404,10 @@ static void sco_sock_init(struct sock *sk, struct sock *parent)
{
BT_DBG("sk %p", sk);
- if (parent)
+ if (parent) {
sk->sk_type = parent->sk_type;
+ security_sk_clone(parent, sk);
+ }
}
static struct proto sco_proto = {
@@ -464,22 +463,18 @@ static int sco_sock_create(struct net *net, struct socket *sock, int protocol,
return 0;
}
-static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
+static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
{
- struct sockaddr_sco sa;
+ struct sockaddr_sco *sa = (struct sockaddr_sco *) addr;
struct sock *sk = sock->sk;
- bdaddr_t *src = &sa.sco_bdaddr;
- int len, err = 0;
+ bdaddr_t *src = &sa->sco_bdaddr;
+ int err = 0;
- BT_DBG("sk %p %s", sk, batostr(&sa.sco_bdaddr));
+ BT_DBG("sk %p %s", sk, batostr(&sa->sco_bdaddr));
if (!addr || addr->sa_family != AF_BLUETOOTH)
return -EINVAL;
- memset(&sa, 0, sizeof(sa));
- len = min_t(unsigned int, sizeof(sa), alen);
- memcpy(&sa, addr, len);
-
lock_sock(sk);
if (sk->sk_state != BT_OPEN) {
@@ -493,8 +488,7 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
err = -EADDRINUSE;
} else {
/* Save source address */
- bacpy(&bt_sk(sk)->src, &sa.sco_bdaddr);
- sco_pi(sk)->pkt_type = sa.sco_pkt_type;
+ bacpy(&bt_sk(sk)->src, &sa->sco_bdaddr);
sk->sk_state = BT_BOUND;
}
@@ -507,34 +501,27 @@ done:
static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
{
+ struct sockaddr_sco *sa = (struct sockaddr_sco *) addr;
struct sock *sk = sock->sk;
- struct sockaddr_sco sa;
- int len, err = 0;
+ int err = 0;
+
BT_DBG("sk %p", sk);
- if (!addr || addr->sa_family != AF_BLUETOOTH)
+ if (alen < sizeof(struct sockaddr_sco) ||
+ addr->sa_family != AF_BLUETOOTH)
return -EINVAL;
- memset(&sa, 0, sizeof(sa));
- len = min_t(unsigned int, sizeof(sa), alen);
- memcpy(&sa, addr, len);
-
- lock_sock(sk);
+ if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND)
+ return -EBADFD;
- if (sk->sk_type != SOCK_SEQPACKET) {
- err = -EINVAL;
- goto done;
- }
+ if (sk->sk_type != SOCK_SEQPACKET)
+ return -EINVAL;
- if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) {
- err = -EBADFD;
- goto done;
- }
+ lock_sock(sk);
/* Set destination address and psm */
- bacpy(&bt_sk(sk)->dst, &sa.sco_bdaddr);
- sco_pi(sk)->pkt_type = sa.sco_pkt_type;
+ bacpy(&bt_sk(sk)->dst, &sa->sco_bdaddr);
err = sco_connect(sk);
if (err)
@@ -641,7 +628,6 @@ static int sco_sock_getname(struct socket *sock, struct sockaddr *addr, int *len
bacpy(&sa->sco_bdaddr, &bt_sk(sk)->dst);
else
bacpy(&sa->sco_bdaddr, &bt_sk(sk)->src);
- sa->sco_pkt_type = sco_pi(sk)->pkt_type;
return 0;
}
@@ -788,7 +774,8 @@ static int sco_sock_shutdown(struct socket *sock, int how)
sco_sock_clear_timer(sk);
__sco_sock_close(sk);
- if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
+ if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime &&
+ !(current->flags & PF_EXITING))
err = bt_sock_wait_state(sk, BT_CLOSED,
sk->sk_lingertime);
}
@@ -808,7 +795,8 @@ static int sco_sock_release(struct socket *sock)
sco_sock_close(sk);
- if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) {
+ if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime &&
+ !(current->flags & PF_EXITING)) {
lock_sock(sk);
err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
release_sock(sk);
@@ -891,11 +879,6 @@ static void sco_conn_ready(struct sco_conn *conn)
bacpy(&bt_sk(sk)->src, conn->src);
bacpy(&bt_sk(sk)->dst, conn->dst);
- if (!conn->hcon) {
- BT_ERR("conn->hcon = NULL");
- /* to do */
- }
-
hci_conn_hold(conn->hcon);
__sco_chan_add(conn, sk, parent);