diff options
Diffstat (limited to 'net/bluetooth/sco.c')
-rw-r--r-- | net/bluetooth/sco.c | 71 |
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); |