[Bluetooth] Add locking for bt_proto array manipulation
authorMarcel Holtmann <marcel@holtmann.org>
Sun, 15 Oct 2006 15:31:14 +0000 (17:31 +0200)
committerDavid S. Miller <davem@sunset.davemloft.net>
Mon, 16 Oct 2006 06:14:34 +0000 (23:14 -0700)
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>
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 a91fee4f27058f19f4301aae08ff0e3f20cd1e97..67df99e2e5c82b2a4fc72e28dc748a33209fcd55 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;
@@ -92,11 +107,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 5d9d6f14b3106e7fc5fded10c6fc59f78eec3930..5563db1bf526e94d4a48c5af511315c4d3646786 100644 (file)
@@ -214,7 +214,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 0547edd57734536d5e3c887e031c49de44ea03f1..53295d33dc5c31eb610c1766e5795f3c7a123cfd 100644 (file)
@@ -205,7 +205,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 1a35d343e08a593f91cc71fce52306a50d991c4b..f26a9eb49945c8805db60c07964b9c1a734f4556 100644 (file)
@@ -618,7 +618,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 6242446aa270fafa94144567ffcedd070388a80e..407fba43c1b973cda01122be9cc3dce198c2b930 100644 (file)
@@ -256,7 +256,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 66fc621a077cd2cb126e3013527fb5fdf014d459..2b3dcb8f90fadebdcde2ace1feed9cd90cf76b0e 100644 (file)
@@ -559,7 +559,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 530cc41f3a22136819a036d094bf4c667d1c71a2..544d65b7baa7de67fe796ec2e4cf68a0c6051e1f 100644 (file)
@@ -336,7 +336,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 14b0f6930637d6f5ce7d13618d796cbfd0161ded..5d13d4f317538e1280118ac7f7f35994437163bf 100644 (file)
@@ -452,7 +452,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);