]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
[Bluetooth] Add locking for bt_proto array manipulation
authorMarcel Holtmann <marcel@holtmann.org>
Thu, 25 Jan 2007 19:38:15 +0000 (20:38 +0100)
committerAdrian Bunk <bunk@stusta.de>
Fri, 26 Jan 2007 19:49:22 +0000 (20:49 +0100)
The bt_proto array needs to be protected by some kind of locking to
prevent a race condition between bt_sock_create and bt_sock_register.

And in addition all calls to sk_alloc need to be made GFP_ATOMIC now.

Signed-off-by: Masatake YAMATO <jet@gyve.org>
Signed-off-by: Frederik Deweerdt <frederik.deweerdt@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Adrian Bunk <bunk@stusta.de>
net/bluetooth/af_bluetooth.c
net/bluetooth/bnep/sock.c
net/bluetooth/cmtp/sock.c
net/bluetooth/hci_sock.c
net/bluetooth/hidp/sock.c
net/bluetooth/l2cap.c
net/bluetooth/rfcomm/sock.c
net/bluetooth/sco.c

index 6ebcc8d4b559b14fceb8b268e4b635f11b06f184..8587844b875673e6ba6e5cc9da12a86642c7cbc7 100644 (file)
 /* Bluetooth sockets */
 #define BT_MAX_PROTO   8
 static struct net_proto_family *bt_proto[BT_MAX_PROTO];
+static DEFINE_RWLOCK(bt_proto_lock);
 
 int bt_sock_register(int proto, struct net_proto_family *ops)
 {
+       int err = 0;
+
        if (proto < 0 || proto >= BT_MAX_PROTO)
                return -EINVAL;
 
+       write_lock(&bt_proto_lock);
+
        if (bt_proto[proto])
-               return -EEXIST;
+               err = -EEXIST;
+       else
+               bt_proto[proto] = ops;
 
-       bt_proto[proto] = ops;
-       return 0;
+       write_unlock(&bt_proto_lock);
+
+       return err;
 }
 EXPORT_SYMBOL(bt_sock_register);
 
 int bt_sock_unregister(int proto)
 {
+       int err = 0;
+
        if (proto < 0 || proto >= BT_MAX_PROTO)
                return -EINVAL;
 
+       write_lock(&bt_proto_lock);
+
        if (!bt_proto[proto])
-               return -ENOENT;
+               err = -ENOENT;
+       else
+               bt_proto[proto] = NULL;
 
-       bt_proto[proto] = NULL;
-       return 0;
+       write_unlock(&bt_proto_lock);
+
+       return err;
 }
 EXPORT_SYMBOL(bt_sock_unregister);
 
 static int bt_sock_create(struct socket *sock, int proto)
 {
-       int err = 0;
+       int err;
 
        if (proto < 0 || proto >= BT_MAX_PROTO)
                return -EINVAL;
@@ -93,11 +108,18 @@ static int bt_sock_create(struct socket *sock, int proto)
                request_module("bt-proto-%d", proto);
        }
 #endif
+
        err = -EPROTONOSUPPORT;
+
+       read_lock(&bt_proto_lock);
+
        if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
                err = bt_proto[proto]->create(sock, proto);
                module_put(bt_proto[proto]->owner);
        }
+
+       read_unlock(&bt_proto_lock);
+
        return err; 
 }
 
index 8f7da1eac83e826cc84ecdacd2441cba3b0ca676..e9b63e61c8398ec3cf26a04784c3d4f3098b8940 100644 (file)
@@ -215,7 +215,7 @@ static int bnep_sock_create(struct socket *sock, int protocol)
        if (sock->type != SOCK_RAW)
                return -ESOCKTNOSUPPORT;
 
-       sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &bnep_proto, 1);
+       sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &bnep_proto, 1);
        if (!sk)
                return -ENOMEM;
 
index 84345d4e3c18e38e41b4504bd23ba1da913c09d1..d29e870bb37974dd1925343f935104b0eca4a86a 100644 (file)
@@ -206,7 +206,7 @@ static int cmtp_sock_create(struct socket *sock, int protocol)
        if (sock->type != SOCK_RAW)
                return -ESOCKTNOSUPPORT;
 
-       sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &cmtp_proto, 1);
+       sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &cmtp_proto, 1);
        if (!sk)
                return -ENOMEM;
 
index 4e86ff478352a4078a27e1a57061809a4560f855..ed117dbe00d486dbb4c55b849220db4cfe4aeb0a 100644 (file)
@@ -622,7 +622,7 @@ static int hci_sock_create(struct socket *sock, int protocol)
 
        sock->ops = &hci_sock_ops;
 
-       sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &hci_sk_proto, 1);
+       sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto, 1);
        if (!sk)
                return -ENOMEM;
 
index 02c94eb000b6d809e9131c5aa5c15f09f85dd8fc..9ebab48b6c7fdc79b0c9e4351d87a509f517eac5 100644 (file)
@@ -257,7 +257,7 @@ static int hidp_sock_create(struct socket *sock, int protocol)
        if (sock->type != SOCK_RAW)
                return -ESOCKTNOSUPPORT;
 
-       sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &hidp_proto, 1);
+       sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &hidp_proto, 1);
        if (!sk)
                return -ENOMEM;
 
index f6b4a8085357a6c0973872665272118516f72816..fc1b54fb0ad25c0814726764be22629776a78138 100644 (file)
@@ -414,7 +414,7 @@ static int l2cap_sock_create(struct socket *sock, int protocol)
 
        sock->ops = &l2cap_sock_ops;
 
-       sk = l2cap_sock_alloc(sock, protocol, GFP_KERNEL);
+       sk = l2cap_sock_alloc(sock, protocol, GFP_ATOMIC);
        if (!sk)
                return -ENOMEM;
 
index f133a1aba3d9820a5bd12ada472afba3d823e28d..54f2a7c91c668074fcb13b9ff663f3f2d735706f 100644 (file)
@@ -337,7 +337,8 @@ static int rfcomm_sock_create(struct socket *sock, int protocol)
 
        sock->ops = &rfcomm_sock_ops;
 
-       if (!(sk = rfcomm_sock_alloc(sock, protocol, GFP_KERNEL)))
+       sk = rfcomm_sock_alloc(sock, protocol, GFP_ATOMIC);
+       if (!sk)
                return -ENOMEM;
 
        rfcomm_sock_init(sk, NULL);
index 6b61323ce23cad772371657cf18833027f56d0f9..d0ed1011b8838efd6cc1d9176e1ffab000bc0bde 100644 (file)
@@ -455,7 +455,8 @@ static int sco_sock_create(struct socket *sock, int protocol)
 
        sock->ops = &sco_sock_ops;
 
-       if (!(sk = sco_sock_alloc(sock, protocol, GFP_KERNEL)))
+       sk = sco_sock_alloc(sock, protocol, GFP_ATOMIC);
+       if (!sk)
                return -ENOMEM;
 
        sco_sock_init(sk, NULL);