diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2013-10-18 04:49:25 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2013-10-18 04:53:57 -0400 |
commit | eb622495e89879bb7d62bb27b2561a306bbe2401 (patch) | |
tree | 7b3c5955524ca3c83f84ff5d8ded8c2ef02ac23a | |
parent | 2bfa3531f654d82db01d3121ae2de7a8696a4555 (diff) |
Bluetooth: Fix ATT socket backwards compatibility with user space
Old user space versions bind the Attribute Protocol socket to
BDADDR_BREDR when they should be using BDADDR_LE_PUBLIC or
BDADDR_LE_RANDOM. The kernel recently introduced stricter checks on the
socket parameters but we need to punch this hole for old user space
versions to keep them working.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 27 |
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; |