Commit 74da626a1098640ddc40c0e3481c0cd41e8ec1e9
Committed by
David S. Miller
1 parent
cb19d9ea2c
Exists in
master
and in
7 other branches
[Bluetooth] Add locking for bt_proto array manipulation
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>
Showing 8 changed files with 38 additions and 14 deletions Side-by-side Diff
net/bluetooth/af_bluetooth.c
... | ... | @@ -53,36 +53,51 @@ |
53 | 53 | /* Bluetooth sockets */ |
54 | 54 | #define BT_MAX_PROTO 8 |
55 | 55 | static struct net_proto_family *bt_proto[BT_MAX_PROTO]; |
56 | +static DEFINE_RWLOCK(bt_proto_lock); | |
56 | 57 | |
57 | 58 | int bt_sock_register(int proto, struct net_proto_family *ops) |
58 | 59 | { |
60 | + int err = 0; | |
61 | + | |
59 | 62 | if (proto < 0 || proto >= BT_MAX_PROTO) |
60 | 63 | return -EINVAL; |
61 | 64 | |
65 | + write_lock(&bt_proto_lock); | |
66 | + | |
62 | 67 | if (bt_proto[proto]) |
63 | - return -EEXIST; | |
68 | + err = -EEXIST; | |
69 | + else | |
70 | + bt_proto[proto] = ops; | |
64 | 71 | |
65 | - bt_proto[proto] = ops; | |
66 | - return 0; | |
72 | + write_unlock(&bt_proto_lock); | |
73 | + | |
74 | + return err; | |
67 | 75 | } |
68 | 76 | EXPORT_SYMBOL(bt_sock_register); |
69 | 77 | |
70 | 78 | int bt_sock_unregister(int proto) |
71 | 79 | { |
80 | + int err = 0; | |
81 | + | |
72 | 82 | if (proto < 0 || proto >= BT_MAX_PROTO) |
73 | 83 | return -EINVAL; |
74 | 84 | |
85 | + write_lock(&bt_proto_lock); | |
86 | + | |
75 | 87 | if (!bt_proto[proto]) |
76 | - return -ENOENT; | |
88 | + err = -ENOENT; | |
89 | + else | |
90 | + bt_proto[proto] = NULL; | |
77 | 91 | |
78 | - bt_proto[proto] = NULL; | |
79 | - return 0; | |
92 | + write_unlock(&bt_proto_lock); | |
93 | + | |
94 | + return err; | |
80 | 95 | } |
81 | 96 | EXPORT_SYMBOL(bt_sock_unregister); |
82 | 97 | |
83 | 98 | static int bt_sock_create(struct socket *sock, int proto) |
84 | 99 | { |
85 | - int err = 0; | |
100 | + int err; | |
86 | 101 | |
87 | 102 | if (proto < 0 || proto >= BT_MAX_PROTO) |
88 | 103 | return -EINVAL; |
89 | 104 | |
90 | 105 | |
... | ... | @@ -92,11 +107,18 @@ |
92 | 107 | request_module("bt-proto-%d", proto); |
93 | 108 | } |
94 | 109 | #endif |
110 | + | |
95 | 111 | err = -EPROTONOSUPPORT; |
112 | + | |
113 | + read_lock(&bt_proto_lock); | |
114 | + | |
96 | 115 | if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) { |
97 | 116 | err = bt_proto[proto]->create(sock, proto); |
98 | 117 | module_put(bt_proto[proto]->owner); |
99 | 118 | } |
119 | + | |
120 | + read_unlock(&bt_proto_lock); | |
121 | + | |
100 | 122 | return err; |
101 | 123 | } |
102 | 124 |
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