]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - net/bluetooth/sco.c
Merge remote-tracking branch 'ipsec/master'
[karo-tx-linux.git] / net / bluetooth / sco.c
index f315c8d0e43b594486cc3dd1be1433387601e7c3..fe129663bd3f7faeb39f20d02a8425d525da071d 100644 (file)
@@ -74,7 +74,7 @@ struct sco_pinfo {
 
 static void sco_sock_timeout(unsigned long arg)
 {
-       struct sock *sk = (struct sock *) arg;
+       struct sock *sk = (struct sock *)arg;
 
        BT_DBG("sock %p state %d", sk, sk->sk_state);
 
@@ -170,18 +170,21 @@ static void sco_conn_del(struct hci_conn *hcon, int err)
        sco_conn_unlock(conn);
 
        if (sk) {
+               sock_hold(sk);
                bh_lock_sock(sk);
                sco_sock_clear_timer(sk);
                sco_chan_del(sk, err);
                bh_unlock_sock(sk);
                sco_sock_kill(sk);
+               sock_put(sk);
        }
 
        hcon->sco_data = NULL;
        kfree(conn);
 }
 
-static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent)
+static void __sco_chan_add(struct sco_conn *conn, struct sock *sk,
+                          struct sock *parent)
 {
        BT_DBG("conn %p", conn);
 
@@ -414,8 +417,10 @@ static void __sco_sock_close(struct sock *sk)
                if (sco_pi(sk)->conn->hcon) {
                        sk->sk_state = BT_DISCONN;
                        sco_sock_set_timer(sk, SCO_DISCONN_TIMEOUT);
+                       sco_conn_lock(sco_pi(sk)->conn);
                        hci_conn_drop(sco_pi(sk)->conn->hcon);
                        sco_pi(sk)->conn->hcon = NULL;
+                       sco_conn_unlock(sco_pi(sk)->conn);
                } else
                        sco_chan_del(sk, ECONNRESET);
                break;
@@ -459,7 +464,8 @@ static struct proto sco_proto = {
        .obj_size       = sizeof(struct sco_pinfo)
 };
 
-static struct sock *sco_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio, int kern)
+static struct sock *sco_sock_alloc(struct net *net, struct socket *sock,
+                                  int proto, gfp_t prio, int kern)
 {
        struct sock *sk;
 
@@ -508,7 +514,8 @@ 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 addr_len)
+static int sco_sock_bind(struct socket *sock, struct sockaddr *addr,
+                        int addr_len)
 {
        struct sockaddr_sco *sa = (struct sockaddr_sco *) addr;
        struct sock *sk = sock->sk;
@@ -615,7 +622,8 @@ done:
        return err;
 }
 
-static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flags)
+static int sco_sock_accept(struct socket *sock, struct socket *newsock,
+                          int flags)
 {
        DEFINE_WAIT_FUNC(wait, woken_wake_function);
        struct sock *sk = sock->sk, *ch;
@@ -669,7 +677,8 @@ done:
        return err;
 }
 
-static int sco_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer)
+static int sco_sock_getname(struct socket *sock, struct sockaddr *addr,
+                           int *len, int peer)
 {
        struct sockaddr_sco *sa = (struct sockaddr_sco *) addr;
        struct sock *sk = sock->sk;
@@ -779,7 +788,8 @@ static int sco_sock_recvmsg(struct socket *sock, struct msghdr *msg,
        return bt_sock_recvmsg(sock, msg, len, flags);
 }
 
-static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
+static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
+                              char __user *optval, unsigned int optlen)
 {
        struct sock *sk = sock->sk;
        int len, err = 0;
@@ -819,7 +829,7 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char
                voice.setting = sco_pi(sk)->setting;
 
                len = min_t(unsigned int, sizeof(voice), optlen);
-               if (copy_from_user((char *) &voice, optval, len)) {
+               if (copy_from_user((char *)&voice, optval, len)) {
                        err = -EFAULT;
                        break;
                }
@@ -843,7 +853,8 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char
        return err;
 }
 
-static int sco_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
+static int sco_sock_getsockopt_old(struct socket *sock, int optname,
+                                  char __user *optval, int __user *optlen)
 {
        struct sock *sk = sock->sk;
        struct sco_options opts;
@@ -903,7 +914,8 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname, char __user
        return err;
 }
 
-static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
+static int sco_sock_getsockopt(struct socket *sock, int level, int optname,
+                              char __user *optval, int __user *optlen)
 {
        struct sock *sk = sock->sk;
        int len, err = 0;
@@ -928,7 +940,7 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char
                }
 
                if (put_user(test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags),
-                            (u32 __user *) optval))
+                            (u32 __user *)optval))
                        err = -EFAULT;
 
                break;
@@ -961,7 +973,9 @@ static int sco_sock_shutdown(struct socket *sock, int how)
        if (!sk)
                return 0;
 
+       sock_hold(sk);
        lock_sock(sk);
+
        if (!sk->sk_shutdown) {
                sk->sk_shutdown = SHUTDOWN_MASK;
                sco_sock_clear_timer(sk);
@@ -972,7 +986,10 @@ static int sco_sock_shutdown(struct socket *sock, int how)
                        err = bt_sock_wait_state(sk, BT_CLOSED,
                                                 sk->sk_lingertime);
        }
+
        release_sock(sk);
+       sock_put(sk);
+
        return err;
 }
 
@@ -1016,6 +1033,11 @@ static void sco_conn_ready(struct sco_conn *conn)
        } else {
                sco_conn_lock(conn);
 
+               if (!conn->hcon) {
+                       sco_conn_unlock(conn);
+                       return;
+               }
+
                parent = sco_get_sock_listen(&conn->hcon->src);
                if (!parent) {
                        sco_conn_unlock(conn);