Skip to content

Commit

Permalink
[Bluetooth] Add locking for bt_proto array manipulation
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Frederik Deweerdt <[email protected]>
Signed-off-by: Marcel Holtmann <[email protected]>
  • Loading branch information
holtmann authored and David S. Miller committed Oct 16, 2006
1 parent cb19d9e commit 74da626
Show file tree
Hide file tree
Showing 8 changed files with 38 additions and 14 deletions.
36 changes: 29 additions & 7 deletions net/bluetooth/af_bluetooth.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,36 +53,51 @@
/* 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;
Expand All @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion net/bluetooth/bnep/sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion net/bluetooth/cmtp/sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion net/bluetooth/hci_sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion net/bluetooth/hidp/sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion net/bluetooth/l2cap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
3 changes: 2 additions & 1 deletion net/bluetooth/rfcomm/sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion net/bluetooth/sco.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 74da626

Please sign in to comment.