aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/l2cap_sock.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 34e5a58ffca8..1f326d9d9132 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -159,8 +159,31 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr,
159 if (!bdaddr_type_is_valid(la.l2_bdaddr_type)) 159 if (!bdaddr_type_is_valid(la.l2_bdaddr_type))
160 return -EINVAL; 160 return -EINVAL;
161 161
162 if (chan->src_type == BDADDR_BREDR && la.l2_bdaddr_type != BDADDR_BREDR) 162 /* Check that the socket wasn't bound to something that
163 return -EINVAL; 163 * conflicts with the address given to connect(). If chan->src
164 * is BDADDR_ANY it means bind() was never used, in which case
165 * chan->src_type and la.l2_bdaddr_type do not need to match.
166 */
167 if (chan->src_type == BDADDR_BREDR && bacmp(&chan->src, BDADDR_ANY) &&
168 bdaddr_type_is_le(la.l2_bdaddr_type)) {
169 /* Old user space versions will try to incorrectly bind
170 * the ATT socket using BDADDR_BREDR. We need to accept
171 * this and fix up the source address type only when
172 * both the source CID and destination CID indicate
173 * ATT. Anything else is an invalid combination.
174 */
175 if (chan->scid != L2CAP_CID_ATT ||
176 la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT))
177 return -EINVAL;
178
179 /* We don't have the hdev available here to make a
180 * better decision on random vs public, but since all
181 * user space versions that exhibit this issue anyway do
182 * not support random local addresses assuming public
183 * here is good enough.
184 */
185 chan->src_type = BDADDR_LE_PUBLIC;
186 }
164 187
165 if (chan->src_type != BDADDR_BREDR && la.l2_bdaddr_type == BDADDR_BREDR) 188 if (chan->src_type != BDADDR_BREDR && la.l2_bdaddr_type == BDADDR_BREDR)
166 return -EINVAL; 189 return -EINVAL;