diff options
-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 4c7de72c27e7..ad0bf5828140 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, |
@@ -584,7 +585,7 @@ ieee80211_rx_mgmt_auth(struct ieee80211_work *wk, | |||
584 | u16 auth_alg, auth_transaction, status_code; | 585 | u16 auth_alg, auth_transaction, status_code; |
585 | 586 | ||
586 | if (wk->type != IEEE80211_WORK_AUTH) | 587 | if (wk->type != IEEE80211_WORK_AUTH) |
587 | return WORK_ACT_NONE; | 588 | return WORK_ACT_MISMATCH; |
588 | 589 | ||
589 | if (len < 24 + 6) | 590 | if (len < 24 + 6) |
590 | return WORK_ACT_NONE; | 591 | return WORK_ACT_NONE; |
@@ -635,6 +636,9 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_work *wk, | |||
635 | struct ieee802_11_elems elems; | 636 | struct ieee802_11_elems elems; |
636 | u8 *pos; | 637 | u8 *pos; |
637 | 638 | ||
639 | if (wk->type != IEEE80211_WORK_ASSOC) | ||
640 | return WORK_ACT_MISMATCH; | ||
641 | |||
638 | /* | 642 | /* |
639 | * AssocResp and ReassocResp have identical structure, so process both | 643 | * AssocResp and ReassocResp have identical structure, so process both |
640 | * of them in this function. | 644 | * of them in this function. |
@@ -690,6 +694,12 @@ ieee80211_rx_mgmt_probe_resp(struct ieee80211_work *wk, | |||
690 | 694 | ||
691 | ASSERT_WORK_MTX(local); | 695 | ASSERT_WORK_MTX(local); |
692 | 696 | ||
697 | if (wk->type != IEEE80211_WORK_DIRECT_PROBE) | ||
698 | return WORK_ACT_MISMATCH; | ||
699 | |||
700 | if (len < 24 + 12) | ||
701 | return WORK_ACT_NONE; | ||
702 | |||
693 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; | 703 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; |
694 | if (baselen > len) | 704 | if (baselen > len) |
695 | return WORK_ACT_NONE; | 705 | return WORK_ACT_NONE; |
@@ -704,7 +714,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | |||
704 | struct ieee80211_rx_status *rx_status; | 714 | struct ieee80211_rx_status *rx_status; |
705 | struct ieee80211_mgmt *mgmt; | 715 | struct ieee80211_mgmt *mgmt; |
706 | struct ieee80211_work *wk; | 716 | struct ieee80211_work *wk; |
707 | enum work_action rma = WORK_ACT_NONE; | 717 | enum work_action rma; |
708 | u16 fc; | 718 | u16 fc; |
709 | 719 | ||
710 | rx_status = (struct ieee80211_rx_status *) skb->cb; | 720 | rx_status = (struct ieee80211_rx_status *) skb->cb; |
@@ -751,7 +761,17 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | |||
751 | break; | 761 | break; |
752 | default: | 762 | default: |
753 | WARN_ON(1); | 763 | WARN_ON(1); |
764 | rma = WORK_ACT_NONE; | ||
754 | } | 765 | } |
766 | |||
767 | /* | ||
768 | * We've either received an unexpected frame, or we have | ||
769 | * multiple work items and need to match the frame to the | ||
770 | * right one. | ||
771 | */ | ||
772 | if (rma == WORK_ACT_MISMATCH) | ||
773 | continue; | ||
774 | |||
755 | /* | 775 | /* |
756 | * We've processed this frame for that work, so it can't | 776 | * We've processed this frame for that work, so it can't |
757 | * belong to another work struct. | 777 | * belong to another work struct. |
@@ -761,6 +781,9 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | |||
761 | } | 781 | } |
762 | 782 | ||
763 | switch (rma) { | 783 | switch (rma) { |
784 | case WORK_ACT_MISMATCH: | ||
785 | /* ignore this unmatched frame */ | ||
786 | break; | ||
764 | case WORK_ACT_NONE: | 787 | case WORK_ACT_NONE: |
765 | break; | 788 | break; |
766 | case WORK_ACT_DONE: | 789 | case WORK_ACT_DONE: |