diff options
Diffstat (limited to 'net/mac80211/work.c')
-rw-r--r-- | net/mac80211/work.c | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 1e1ea3007b06..b0ba58589ca3 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #define IEEE80211_MAX_PROBE_TRIES 5 | 32 | #define IEEE80211_MAX_PROBE_TRIES 5 |
33 | 33 | ||
34 | enum work_action { | 34 | enum work_action { |
35 | WORK_ACT_MISMATCH, | ||
35 | WORK_ACT_NONE, | 36 | WORK_ACT_NONE, |
36 | WORK_ACT_TIMEOUT, | 37 | WORK_ACT_TIMEOUT, |
37 | WORK_ACT_DONE, | 38 | WORK_ACT_DONE, |
@@ -574,7 +575,7 @@ ieee80211_rx_mgmt_auth(struct ieee80211_work *wk, | |||
574 | u16 auth_alg, auth_transaction, status_code; | 575 | u16 auth_alg, auth_transaction, status_code; |
575 | 576 | ||
576 | if (wk->type != IEEE80211_WORK_AUTH) | 577 | if (wk->type != IEEE80211_WORK_AUTH) |
577 | return WORK_ACT_NONE; | 578 | return WORK_ACT_MISMATCH; |
578 | 579 | ||
579 | if (len < 24 + 6) | 580 | if (len < 24 + 6) |
580 | return WORK_ACT_NONE; | 581 | return WORK_ACT_NONE; |
@@ -625,6 +626,9 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_work *wk, | |||
625 | struct ieee802_11_elems elems; | 626 | struct ieee802_11_elems elems; |
626 | u8 *pos; | 627 | u8 *pos; |
627 | 628 | ||
629 | if (wk->type != IEEE80211_WORK_ASSOC) | ||
630 | return WORK_ACT_MISMATCH; | ||
631 | |||
628 | /* | 632 | /* |
629 | * AssocResp and ReassocResp have identical structure, so process both | 633 | * AssocResp and ReassocResp have identical structure, so process both |
630 | * of them in this function. | 634 | * of them in this function. |
@@ -680,6 +684,12 @@ ieee80211_rx_mgmt_probe_resp(struct ieee80211_work *wk, | |||
680 | 684 | ||
681 | ASSERT_WORK_MTX(local); | 685 | ASSERT_WORK_MTX(local); |
682 | 686 | ||
687 | if (wk->type != IEEE80211_WORK_DIRECT_PROBE) | ||
688 | return WORK_ACT_MISMATCH; | ||
689 | |||
690 | if (len < 24 + 12) | ||
691 | return WORK_ACT_NONE; | ||
692 | |||
683 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; | 693 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; |
684 | if (baselen > len) | 694 | if (baselen > len) |
685 | return WORK_ACT_NONE; | 695 | return WORK_ACT_NONE; |
@@ -694,7 +704,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | |||
694 | struct ieee80211_rx_status *rx_status; | 704 | struct ieee80211_rx_status *rx_status; |
695 | struct ieee80211_mgmt *mgmt; | 705 | struct ieee80211_mgmt *mgmt; |
696 | struct ieee80211_work *wk; | 706 | struct ieee80211_work *wk; |
697 | enum work_action rma = WORK_ACT_NONE; | 707 | enum work_action rma; |
698 | u16 fc; | 708 | u16 fc; |
699 | 709 | ||
700 | rx_status = (struct ieee80211_rx_status *) skb->cb; | 710 | rx_status = (struct ieee80211_rx_status *) skb->cb; |
@@ -741,7 +751,17 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | |||
741 | break; | 751 | break; |
742 | default: | 752 | default: |
743 | WARN_ON(1); | 753 | WARN_ON(1); |
754 | rma = WORK_ACT_NONE; | ||
744 | } | 755 | } |
756 | |||
757 | /* | ||
758 | * We've either received an unexpected frame, or we have | ||
759 | * multiple work items and need to match the frame to the | ||
760 | * right one. | ||
761 | */ | ||
762 | if (rma == WORK_ACT_MISMATCH) | ||
763 | continue; | ||
764 | |||
745 | /* | 765 | /* |
746 | * We've processed this frame for that work, so it can't | 766 | * We've processed this frame for that work, so it can't |
747 | * belong to another work struct. | 767 | * belong to another work struct. |
@@ -751,6 +771,9 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | |||
751 | } | 771 | } |
752 | 772 | ||
753 | switch (rma) { | 773 | switch (rma) { |
774 | case WORK_ACT_MISMATCH: | ||
775 | /* ignore this unmatched frame */ | ||
776 | break; | ||
754 | case WORK_ACT_NONE: | 777 | case WORK_ACT_NONE: |
755 | break; | 778 | break; |
756 | case WORK_ACT_DONE: | 779 | case WORK_ACT_DONE: |