.. | .. |
---|
30 | 30 | hdr->endpoint_id = epid; |
---|
31 | 31 | hdr->flags = flags; |
---|
32 | 32 | hdr->payload_len = cpu_to_be16(len); |
---|
| 33 | + memset(hdr->control, 0, sizeof(hdr->control)); |
---|
33 | 34 | |
---|
34 | 35 | status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb); |
---|
35 | 36 | |
---|
.. | .. |
---|
113 | 114 | |
---|
114 | 115 | if (svc_rspmsg->status == HTC_SERVICE_SUCCESS) { |
---|
115 | 116 | epid = svc_rspmsg->endpoint_id; |
---|
116 | | - if (epid < 0 || epid >= ENDPOINT_MAX) |
---|
| 117 | + |
---|
| 118 | + /* Check that the received epid for the endpoint to attach |
---|
| 119 | + * a new service is valid. ENDPOINT0 can't be used here as it |
---|
| 120 | + * is already reserved for HTC_CTRL_RSVD_SVC service and thus |
---|
| 121 | + * should not be modified. |
---|
| 122 | + */ |
---|
| 123 | + if (epid <= ENDPOINT0 || epid >= ENDPOINT_MAX) |
---|
117 | 124 | return; |
---|
118 | 125 | |
---|
119 | 126 | service_id = be16_to_cpu(svc_rspmsg->service_id); |
---|
.. | .. |
---|
173 | 180 | time_left = wait_for_completion_timeout(&target->cmd_wait, HZ); |
---|
174 | 181 | if (!time_left) { |
---|
175 | 182 | dev_err(target->dev, "HTC credit config timeout\n"); |
---|
176 | | - kfree_skb(skb); |
---|
177 | 183 | return -ETIMEDOUT; |
---|
178 | 184 | } |
---|
179 | 185 | |
---|
.. | .. |
---|
209 | 215 | time_left = wait_for_completion_timeout(&target->cmd_wait, HZ); |
---|
210 | 216 | if (!time_left) { |
---|
211 | 217 | dev_err(target->dev, "HTC start timeout\n"); |
---|
212 | | - kfree_skb(skb); |
---|
213 | 218 | return -ETIMEDOUT; |
---|
214 | 219 | } |
---|
215 | 220 | |
---|
.. | .. |
---|
274 | 279 | conn_msg->dl_pipeid = endpoint->dl_pipeid; |
---|
275 | 280 | conn_msg->ul_pipeid = endpoint->ul_pipeid; |
---|
276 | 281 | |
---|
| 282 | + /* To prevent infoleak */ |
---|
| 283 | + conn_msg->svc_meta_len = 0; |
---|
| 284 | + conn_msg->pad = 0; |
---|
| 285 | + |
---|
277 | 286 | ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0); |
---|
278 | 287 | if (ret) |
---|
279 | 288 | goto err; |
---|
.. | .. |
---|
282 | 291 | if (!time_left) { |
---|
283 | 292 | dev_err(target->dev, "Service connection timeout for: %d\n", |
---|
284 | 293 | service_connreq->service_id); |
---|
285 | | - kfree_skb(skb); |
---|
286 | 294 | return -ETIMEDOUT; |
---|
287 | 295 | } |
---|
288 | 296 | |
---|
.. | .. |
---|
362 | 370 | } |
---|
363 | 371 | |
---|
364 | 372 | static void ath9k_htc_fw_panic_report(struct htc_target *htc_handle, |
---|
365 | | - struct sk_buff *skb) |
---|
| 373 | + struct sk_buff *skb, u32 len) |
---|
366 | 374 | { |
---|
367 | 375 | uint32_t *pattern = (uint32_t *)skb->data; |
---|
368 | 376 | |
---|
369 | | - switch (*pattern) { |
---|
370 | | - case 0x33221199: |
---|
371 | | - { |
---|
| 377 | + if (*pattern == 0x33221199 && len >= sizeof(struct htc_panic_bad_vaddr)) { |
---|
372 | 378 | struct htc_panic_bad_vaddr *htc_panic; |
---|
373 | 379 | htc_panic = (struct htc_panic_bad_vaddr *) skb->data; |
---|
374 | 380 | dev_err(htc_handle->dev, "ath: firmware panic! " |
---|
375 | 381 | "exccause: 0x%08x; pc: 0x%08x; badvaddr: 0x%08x.\n", |
---|
376 | 382 | htc_panic->exccause, htc_panic->pc, |
---|
377 | 383 | htc_panic->badvaddr); |
---|
378 | | - break; |
---|
379 | | - } |
---|
380 | | - case 0x33221299: |
---|
381 | | - { |
---|
| 384 | + return; |
---|
| 385 | + } |
---|
| 386 | + if (*pattern == 0x33221299) { |
---|
382 | 387 | struct htc_panic_bad_epid *htc_panic; |
---|
383 | 388 | htc_panic = (struct htc_panic_bad_epid *) skb->data; |
---|
384 | 389 | dev_err(htc_handle->dev, "ath: firmware panic! " |
---|
385 | 390 | "bad epid: 0x%08x\n", htc_panic->epid); |
---|
386 | | - break; |
---|
387 | | - } |
---|
388 | | - default: |
---|
389 | | - dev_err(htc_handle->dev, "ath: unknown panic pattern!\n"); |
---|
390 | | - break; |
---|
| 391 | + return; |
---|
391 | 392 | } |
---|
| 393 | + dev_err(htc_handle->dev, "ath: unknown panic pattern!\n"); |
---|
392 | 394 | } |
---|
393 | 395 | |
---|
394 | 396 | /* |
---|
395 | 397 | * HTC Messages are handled directly here and the obtained SKB |
---|
396 | 398 | * is freed. |
---|
397 | 399 | * |
---|
398 | | - * Service messages (Data, WMI) passed to the corresponding |
---|
| 400 | + * Service messages (Data, WMI) are passed to the corresponding |
---|
399 | 401 | * endpoint RX handlers, which have to free the SKB. |
---|
400 | 402 | */ |
---|
401 | 403 | void ath9k_htc_rx_msg(struct htc_target *htc_handle, |
---|
.. | .. |
---|
409 | 411 | if (!htc_handle || !skb) |
---|
410 | 412 | return; |
---|
411 | 413 | |
---|
| 414 | + /* A valid message requires len >= 8. |
---|
| 415 | + * |
---|
| 416 | + * sizeof(struct htc_frame_hdr) == 8 |
---|
| 417 | + * sizeof(struct htc_ready_msg) == 8 |
---|
| 418 | + * sizeof(struct htc_panic_bad_vaddr) == 16 |
---|
| 419 | + * sizeof(struct htc_panic_bad_epid) == 8 |
---|
| 420 | + */ |
---|
| 421 | + if (unlikely(len < sizeof(struct htc_frame_hdr))) |
---|
| 422 | + goto invalid; |
---|
412 | 423 | htc_hdr = (struct htc_frame_hdr *) skb->data; |
---|
413 | 424 | epid = htc_hdr->endpoint_id; |
---|
414 | 425 | |
---|
415 | 426 | if (epid == 0x99) { |
---|
416 | | - ath9k_htc_fw_panic_report(htc_handle, skb); |
---|
| 427 | + ath9k_htc_fw_panic_report(htc_handle, skb, len); |
---|
417 | 428 | kfree_skb(skb); |
---|
418 | 429 | return; |
---|
419 | 430 | } |
---|
420 | 431 | |
---|
421 | 432 | if (epid < 0 || epid >= ENDPOINT_MAX) { |
---|
| 433 | +invalid: |
---|
422 | 434 | if (pipe_id != USB_REG_IN_PIPE) |
---|
423 | 435 | dev_kfree_skb_any(skb); |
---|
424 | 436 | else |
---|
.. | .. |
---|
430 | 442 | |
---|
431 | 443 | /* Handle trailer */ |
---|
432 | 444 | if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER) { |
---|
433 | | - if (be32_to_cpu(*(__be32 *) skb->data) == 0x00C60000) |
---|
| 445 | + if (be32_to_cpu(*(__be32 *) skb->data) == 0x00C60000) { |
---|
434 | 446 | /* Move past the Watchdog pattern */ |
---|
435 | 447 | htc_hdr = (struct htc_frame_hdr *)(skb->data + 4); |
---|
| 448 | + len -= 4; |
---|
| 449 | + } |
---|
436 | 450 | } |
---|
437 | 451 | |
---|
438 | 452 | /* Get the message ID */ |
---|
| 453 | + if (unlikely(len < sizeof(struct htc_frame_hdr) + sizeof(__be16))) |
---|
| 454 | + goto invalid; |
---|
439 | 455 | msg_id = (__be16 *) ((void *) htc_hdr + |
---|
440 | 456 | sizeof(struct htc_frame_hdr)); |
---|
441 | 457 | |
---|
442 | 458 | /* Now process HTC messages */ |
---|
443 | 459 | switch (be16_to_cpu(*msg_id)) { |
---|
444 | 460 | case HTC_MSG_READY_ID: |
---|
| 461 | + if (unlikely(len < sizeof(struct htc_ready_msg))) |
---|
| 462 | + goto invalid; |
---|
445 | 463 | htc_process_target_rdy(htc_handle, htc_hdr); |
---|
446 | 464 | break; |
---|
447 | 465 | case HTC_MSG_CONNECT_SERVICE_RESPONSE_ID: |
---|
| 466 | + if (unlikely(len < sizeof(struct htc_frame_hdr) + |
---|
| 467 | + sizeof(struct htc_conn_svc_rspmsg))) |
---|
| 468 | + goto invalid; |
---|
448 | 469 | htc_process_conn_rsp(htc_handle, htc_hdr); |
---|
449 | 470 | break; |
---|
450 | 471 | default: |
---|
.. | .. |
---|
463 | 484 | if (endpoint->ep_callbacks.rx) |
---|
464 | 485 | endpoint->ep_callbacks.rx(endpoint->ep_callbacks.priv, |
---|
465 | 486 | skb, epid); |
---|
| 487 | + else |
---|
| 488 | + goto invalid; |
---|
466 | 489 | } |
---|
467 | 490 | } |
---|
468 | 491 | |
---|