| .. | .. |
|---|
| 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 | |
|---|
| .. | .. |
|---|
| 173 | 174 | time_left = wait_for_completion_timeout(&target->cmd_wait, HZ); |
|---|
| 174 | 175 | if (!time_left) { |
|---|
| 175 | 176 | dev_err(target->dev, "HTC credit config timeout\n"); |
|---|
| 176 | | - kfree_skb(skb); |
|---|
| 177 | 177 | return -ETIMEDOUT; |
|---|
| 178 | 178 | } |
|---|
| 179 | 179 | |
|---|
| .. | .. |
|---|
| 209 | 209 | time_left = wait_for_completion_timeout(&target->cmd_wait, HZ); |
|---|
| 210 | 210 | if (!time_left) { |
|---|
| 211 | 211 | dev_err(target->dev, "HTC start timeout\n"); |
|---|
| 212 | | - kfree_skb(skb); |
|---|
| 213 | 212 | return -ETIMEDOUT; |
|---|
| 214 | 213 | } |
|---|
| 215 | 214 | |
|---|
| .. | .. |
|---|
| 274 | 273 | conn_msg->dl_pipeid = endpoint->dl_pipeid; |
|---|
| 275 | 274 | conn_msg->ul_pipeid = endpoint->ul_pipeid; |
|---|
| 276 | 275 | |
|---|
| 276 | + /* To prevent infoleak */ |
|---|
| 277 | + conn_msg->svc_meta_len = 0; |
|---|
| 278 | + conn_msg->pad = 0; |
|---|
| 279 | + |
|---|
| 277 | 280 | ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0); |
|---|
| 278 | 281 | if (ret) |
|---|
| 279 | 282 | goto err; |
|---|
| .. | .. |
|---|
| 282 | 285 | if (!time_left) { |
|---|
| 283 | 286 | dev_err(target->dev, "Service connection timeout for: %d\n", |
|---|
| 284 | 287 | service_connreq->service_id); |
|---|
| 285 | | - kfree_skb(skb); |
|---|
| 286 | 288 | return -ETIMEDOUT; |
|---|
| 287 | 289 | } |
|---|
| 288 | 290 | |
|---|
| .. | .. |
|---|
| 362 | 364 | } |
|---|
| 363 | 365 | |
|---|
| 364 | 366 | static void ath9k_htc_fw_panic_report(struct htc_target *htc_handle, |
|---|
| 365 | | - struct sk_buff *skb) |
|---|
| 367 | + struct sk_buff *skb, u32 len) |
|---|
| 366 | 368 | { |
|---|
| 367 | 369 | uint32_t *pattern = (uint32_t *)skb->data; |
|---|
| 368 | 370 | |
|---|
| 369 | | - switch (*pattern) { |
|---|
| 370 | | - case 0x33221199: |
|---|
| 371 | | - { |
|---|
| 371 | + if (*pattern == 0x33221199 && len >= sizeof(struct htc_panic_bad_vaddr)) { |
|---|
| 372 | 372 | struct htc_panic_bad_vaddr *htc_panic; |
|---|
| 373 | 373 | htc_panic = (struct htc_panic_bad_vaddr *) skb->data; |
|---|
| 374 | 374 | dev_err(htc_handle->dev, "ath: firmware panic! " |
|---|
| 375 | 375 | "exccause: 0x%08x; pc: 0x%08x; badvaddr: 0x%08x.\n", |
|---|
| 376 | 376 | htc_panic->exccause, htc_panic->pc, |
|---|
| 377 | 377 | htc_panic->badvaddr); |
|---|
| 378 | | - break; |
|---|
| 379 | | - } |
|---|
| 380 | | - case 0x33221299: |
|---|
| 381 | | - { |
|---|
| 378 | + return; |
|---|
| 379 | + } |
|---|
| 380 | + if (*pattern == 0x33221299) { |
|---|
| 382 | 381 | struct htc_panic_bad_epid *htc_panic; |
|---|
| 383 | 382 | htc_panic = (struct htc_panic_bad_epid *) skb->data; |
|---|
| 384 | 383 | dev_err(htc_handle->dev, "ath: firmware panic! " |
|---|
| 385 | 384 | "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; |
|---|
| 385 | + return; |
|---|
| 391 | 386 | } |
|---|
| 387 | + dev_err(htc_handle->dev, "ath: unknown panic pattern!\n"); |
|---|
| 392 | 388 | } |
|---|
| 393 | 389 | |
|---|
| 394 | 390 | /* |
|---|
| .. | .. |
|---|
| 409 | 405 | if (!htc_handle || !skb) |
|---|
| 410 | 406 | return; |
|---|
| 411 | 407 | |
|---|
| 408 | + /* A valid message requires len >= 8. |
|---|
| 409 | + * |
|---|
| 410 | + * sizeof(struct htc_frame_hdr) == 8 |
|---|
| 411 | + * sizeof(struct htc_ready_msg) == 8 |
|---|
| 412 | + * sizeof(struct htc_panic_bad_vaddr) == 16 |
|---|
| 413 | + * sizeof(struct htc_panic_bad_epid) == 8 |
|---|
| 414 | + */ |
|---|
| 415 | + if (unlikely(len < sizeof(struct htc_frame_hdr))) |
|---|
| 416 | + goto invalid; |
|---|
| 412 | 417 | htc_hdr = (struct htc_frame_hdr *) skb->data; |
|---|
| 413 | 418 | epid = htc_hdr->endpoint_id; |
|---|
| 414 | 419 | |
|---|
| 415 | 420 | if (epid == 0x99) { |
|---|
| 416 | | - ath9k_htc_fw_panic_report(htc_handle, skb); |
|---|
| 421 | + ath9k_htc_fw_panic_report(htc_handle, skb, len); |
|---|
| 417 | 422 | kfree_skb(skb); |
|---|
| 418 | 423 | return; |
|---|
| 419 | 424 | } |
|---|
| 420 | 425 | |
|---|
| 421 | 426 | if (epid < 0 || epid >= ENDPOINT_MAX) { |
|---|
| 427 | +invalid: |
|---|
| 422 | 428 | if (pipe_id != USB_REG_IN_PIPE) |
|---|
| 423 | 429 | dev_kfree_skb_any(skb); |
|---|
| 424 | 430 | else |
|---|
| .. | .. |
|---|
| 430 | 436 | |
|---|
| 431 | 437 | /* Handle trailer */ |
|---|
| 432 | 438 | if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER) { |
|---|
| 433 | | - if (be32_to_cpu(*(__be32 *) skb->data) == 0x00C60000) |
|---|
| 439 | + if (be32_to_cpu(*(__be32 *) skb->data) == 0x00C60000) { |
|---|
| 434 | 440 | /* Move past the Watchdog pattern */ |
|---|
| 435 | 441 | htc_hdr = (struct htc_frame_hdr *)(skb->data + 4); |
|---|
| 442 | + len -= 4; |
|---|
| 443 | + } |
|---|
| 436 | 444 | } |
|---|
| 437 | 445 | |
|---|
| 438 | 446 | /* Get the message ID */ |
|---|
| 447 | + if (unlikely(len < sizeof(struct htc_frame_hdr) + sizeof(__be16))) |
|---|
| 448 | + goto invalid; |
|---|
| 439 | 449 | msg_id = (__be16 *) ((void *) htc_hdr + |
|---|
| 440 | 450 | sizeof(struct htc_frame_hdr)); |
|---|
| 441 | 451 | |
|---|
| 442 | 452 | /* Now process HTC messages */ |
|---|
| 443 | 453 | switch (be16_to_cpu(*msg_id)) { |
|---|
| 444 | 454 | case HTC_MSG_READY_ID: |
|---|
| 455 | + if (unlikely(len < sizeof(struct htc_ready_msg))) |
|---|
| 456 | + goto invalid; |
|---|
| 445 | 457 | htc_process_target_rdy(htc_handle, htc_hdr); |
|---|
| 446 | 458 | break; |
|---|
| 447 | 459 | case HTC_MSG_CONNECT_SERVICE_RESPONSE_ID: |
|---|
| 460 | + if (unlikely(len < sizeof(struct htc_frame_hdr) + |
|---|
| 461 | + sizeof(struct htc_conn_svc_rspmsg))) |
|---|
| 462 | + goto invalid; |
|---|
| 448 | 463 | htc_process_conn_rsp(htc_handle, htc_hdr); |
|---|
| 449 | 464 | break; |
|---|
| 450 | 465 | default: |
|---|