Commit 74da626a1098640ddc40c0e3481c0cd41e8ec1e9

Authored by Marcel Holtmann
Committed by David S. Miller
1 parent cb19d9ea2c

[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
... ... @@ -214,7 +214,7 @@
214 214 if (sock->type != SOCK_RAW)
215 215 return -ESOCKTNOSUPPORT;
216 216  
217   - sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &bnep_proto, 1);
  217 + sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &bnep_proto, 1);
218 218 if (!sk)
219 219 return -ENOMEM;
220 220  
net/bluetooth/cmtp/sock.c
... ... @@ -205,7 +205,7 @@
205 205 if (sock->type != SOCK_RAW)
206 206 return -ESOCKTNOSUPPORT;
207 207  
208   - sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &cmtp_proto, 1);
  208 + sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &cmtp_proto, 1);
209 209 if (!sk)
210 210 return -ENOMEM;
211 211  
net/bluetooth/hci_sock.c
... ... @@ -618,7 +618,7 @@
618 618  
619 619 sock->ops = &hci_sock_ops;
620 620  
621   - sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &hci_sk_proto, 1);
  621 + sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto, 1);
622 622 if (!sk)
623 623 return -ENOMEM;
624 624  
net/bluetooth/hidp/sock.c
... ... @@ -256,7 +256,7 @@
256 256 if (sock->type != SOCK_RAW)
257 257 return -ESOCKTNOSUPPORT;
258 258  
259   - sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &hidp_proto, 1);
  259 + sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &hidp_proto, 1);
260 260 if (!sk)
261 261 return -ENOMEM;
262 262  
net/bluetooth/l2cap.c
... ... @@ -559,7 +559,7 @@
559 559  
560 560 sock->ops = &l2cap_sock_ops;
561 561  
562   - sk = l2cap_sock_alloc(sock, protocol, GFP_KERNEL);
  562 + sk = l2cap_sock_alloc(sock, protocol, GFP_ATOMIC);
563 563 if (!sk)
564 564 return -ENOMEM;
565 565  
net/bluetooth/rfcomm/sock.c
... ... @@ -336,7 +336,8 @@
336 336  
337 337 sock->ops = &rfcomm_sock_ops;
338 338  
339   - if (!(sk = rfcomm_sock_alloc(sock, protocol, GFP_KERNEL)))
  339 + sk = rfcomm_sock_alloc(sock, protocol, GFP_ATOMIC);
  340 + if (!sk)
340 341 return -ENOMEM;
341 342  
342 343 rfcomm_sock_init(sk, NULL);
... ... @@ -452,7 +452,8 @@
452 452  
453 453 sock->ops = &sco_sock_ops;
454 454  
455   - if (!(sk = sco_sock_alloc(sock, protocol, GFP_KERNEL)))
  455 + sk = sco_sock_alloc(sock, protocol, GFP_ATOMIC);
  456 + if (!sk)
456 457 return -ENOMEM;
457 458  
458 459 sco_sock_init(sk, NULL);