aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/bluetooth/cmtp/capi.c39
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;