aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2010-05-11 06:42:04 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-05-12 16:28:52 -0400
commitb8d92c9c141ee3dc9b3537b1f0ffb4a54ea8d9b2 (patch)
tree9dee2ac8738e17242e2c891e8941dd43ca9c9189
parent562db532760827f6ce30801a08e6b568848bc9f2 (diff)
mac80211: don't process work item with wrong frame
When we process a frame, we currently just match it to the work struct by the MAC addresses, and not by the work type. This means that we can end up doing the work for an association request item when (for whatever reason) we receive another frame type, for example a probe response. Processing the wrong type of frame will lead to completely invalid data being processed, and will lead to various problems like thinking the association was successful even if the AP never sent an assocation response. Fix this by making each processing function check that it is invoked for the right work struct type only and continue processing otherwise (and drop frames that we didn't expect). This bug was uncovered during the debugging for https://bugzilla.kernel.org/show_bug.cgi?id=15862 but doesn't seem to be the cause for any of the various problems reported there. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--net/mac80211/work.c27
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
34enum work_action { 34enum 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: