diff options
-rw-r--r-- | net/bluetooth/cmtp/capi.c | 39 |
1 files changed, 33 insertions, 6 deletions
diff --git a/net/bluetooth/cmtp/capi.c b/net/bluetooth/cmtp/capi.c index be04e9fb11f6..ab166b48ce8d 100644 --- a/net/bluetooth/cmtp/capi.c +++ b/net/bluetooth/cmtp/capi.c | |||
@@ -196,6 +196,9 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s | |||
196 | 196 | ||
197 | switch (CAPIMSG_SUBCOMMAND(skb->data)) { | 197 | switch (CAPIMSG_SUBCOMMAND(skb->data)) { |
198 | case CAPI_CONF: | 198 | case CAPI_CONF: |
199 | if (skb->len < CAPI_MSG_BASELEN + 10) | ||
200 | break; | ||
201 | |||
199 | func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 5); | 202 | func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 5); |
200 | info = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 8); | 203 | info = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 8); |
201 | 204 | ||
@@ -226,6 +229,9 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s | |||
226 | break; | 229 | break; |
227 | 230 | ||
228 | case CAPI_FUNCTION_GET_PROFILE: | 231 | case CAPI_FUNCTION_GET_PROFILE: |
232 | if (skb->len < CAPI_MSG_BASELEN + 11 + sizeof(capi_profile)) | ||
233 | break; | ||
234 | |||
229 | controller = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 11); | 235 | controller = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 11); |
230 | msgnum = CAPIMSG_MSGID(skb->data); | 236 | msgnum = CAPIMSG_MSGID(skb->data); |
231 | 237 | ||
@@ -246,17 +252,26 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s | |||
246 | break; | 252 | break; |
247 | 253 | ||
248 | case CAPI_FUNCTION_GET_MANUFACTURER: | 254 | case CAPI_FUNCTION_GET_MANUFACTURER: |
255 | if (skb->len < CAPI_MSG_BASELEN + 15) | ||
256 | break; | ||
257 | |||
249 | controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 10); | 258 | controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 10); |
250 | 259 | ||
251 | if (!info && ctrl) { | 260 | if (!info && ctrl) { |
261 | int len = min_t(uint, CAPI_MANUFACTURER_LEN, | ||
262 | skb->data[CAPI_MSG_BASELEN + 14]); | ||
263 | |||
264 | memset(ctrl->manu, 0, CAPI_MANUFACTURER_LEN); | ||
252 | strncpy(ctrl->manu, | 265 | strncpy(ctrl->manu, |
253 | skb->data + CAPI_MSG_BASELEN + 15, | 266 | skb->data + CAPI_MSG_BASELEN + 15, len); |
254 | skb->data[CAPI_MSG_BASELEN + 14]); | ||
255 | } | 267 | } |
256 | 268 | ||
257 | break; | 269 | break; |
258 | 270 | ||
259 | case CAPI_FUNCTION_GET_VERSION: | 271 | case CAPI_FUNCTION_GET_VERSION: |
272 | if (skb->len < CAPI_MSG_BASELEN + 32) | ||
273 | break; | ||
274 | |||
260 | controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12); | 275 | controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12); |
261 | 276 | ||
262 | if (!info && ctrl) { | 277 | if (!info && ctrl) { |
@@ -269,13 +284,18 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s | |||
269 | break; | 284 | break; |
270 | 285 | ||
271 | case CAPI_FUNCTION_GET_SERIAL_NUMBER: | 286 | case CAPI_FUNCTION_GET_SERIAL_NUMBER: |
287 | if (skb->len < CAPI_MSG_BASELEN + 17) | ||
288 | break; | ||
289 | |||
272 | controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12); | 290 | controller = CAPIMSG_U32(skb->data, CAPI_MSG_BASELEN + 12); |
273 | 291 | ||
274 | if (!info && ctrl) { | 292 | if (!info && ctrl) { |
293 | int len = min_t(uint, CAPI_SERIAL_LEN, | ||
294 | skb->data[CAPI_MSG_BASELEN + 16]); | ||
295 | |||
275 | memset(ctrl->serial, 0, CAPI_SERIAL_LEN); | 296 | memset(ctrl->serial, 0, CAPI_SERIAL_LEN); |
276 | strncpy(ctrl->serial, | 297 | strncpy(ctrl->serial, |
277 | skb->data + CAPI_MSG_BASELEN + 17, | 298 | skb->data + CAPI_MSG_BASELEN + 17, len); |
278 | skb->data[CAPI_MSG_BASELEN + 16]); | ||
279 | } | 299 | } |
280 | 300 | ||
281 | break; | 301 | break; |
@@ -284,14 +304,18 @@ static void cmtp_recv_interopmsg(struct cmtp_session *session, struct sk_buff *s | |||
284 | break; | 304 | break; |
285 | 305 | ||
286 | case CAPI_IND: | 306 | case CAPI_IND: |
307 | if (skb->len < CAPI_MSG_BASELEN + 6) | ||
308 | break; | ||
309 | |||
287 | func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3); | 310 | func = CAPIMSG_U16(skb->data, CAPI_MSG_BASELEN + 3); |
288 | 311 | ||
289 | if (func == CAPI_FUNCTION_LOOPBACK) { | 312 | if (func == CAPI_FUNCTION_LOOPBACK) { |
313 | int len = min_t(uint, skb->len - CAPI_MSG_BASELEN - 6, | ||
314 | skb->data[CAPI_MSG_BASELEN + 5]); | ||
290 | appl = CAPIMSG_APPID(skb->data); | 315 | appl = CAPIMSG_APPID(skb->data); |
291 | msgnum = CAPIMSG_MSGID(skb->data); | 316 | msgnum = CAPIMSG_MSGID(skb->data); |
292 | cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func, | 317 | cmtp_send_interopmsg(session, CAPI_RESP, appl, msgnum, func, |
293 | skb->data + CAPI_MSG_BASELEN + 6, | 318 | skb->data + CAPI_MSG_BASELEN + 6, len); |
294 | skb->data[CAPI_MSG_BASELEN + 5]); | ||
295 | } | 319 | } |
296 | 320 | ||
297 | break; | 321 | break; |
@@ -309,6 +333,9 @@ void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb) | |||
309 | 333 | ||
310 | BT_DBG("session %p skb %p len %d", session, skb, skb->len); | 334 | BT_DBG("session %p skb %p len %d", session, skb, skb->len); |
311 | 335 | ||
336 | if (skb->len < CAPI_MSG_BASELEN) | ||
337 | return; | ||
338 | |||
312 | if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) { | 339 | if (CAPIMSG_COMMAND(skb->data) == CAPI_INTEROPERABILITY) { |
313 | cmtp_recv_interopmsg(session, skb); | 340 | cmtp_recv_interopmsg(session, skb); |
314 | return; | 341 | return; |