| From d12c74528e3065c90df70fbc06ec6ffd6e804738 Mon Sep 17 00:00:00 2001 |
| From: Christian Lamparter <chunkeey@googlemail.com> |
| Date: Fri, 8 Oct 2010 22:27:07 +0200 |
| Subject: mac80211: fix possible null-pointer de-reference |
| |
| From: Christian Lamparter <chunkeey@googlemail.com> |
| |
| commit d12c74528e3065c90df70fbc06ec6ffd6e804738 upstream. |
| |
| This patch not only fixes a null-pointer de-reference |
| that would be triggered by a PLINK_OPEN frame with mis- |
| matching/incompatible mesh configuration, but also |
| responds correctly to non-compatible PLINK_OPEN frames |
| by generating a PLINK_CLOSE with the right reason code. |
| |
| The original bug was detected by smatch. |
| ( http://repo.or.cz/w/smatch.git ) |
| |
| net/mac80211/mesh_plink.c +574 mesh_rx_plink_frame(168) |
| error: we previously assumed 'sta' could be null. |
| |
| Reviewed-and-Tested-by: Steve deRosier <steve@cozybit.com> |
| Reviewed-and-Tested-by: Javier Cardona <javier@cozybit.com> |
| Acked-by: Johannes Berg <johannes@sipsolutions.net> |
| Signed-off-by: Christian Lamparter <chunkeey@googlemail.com> |
| Signed-off-by: John W. Linville <linville@tuxdriver.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| net/mac80211/mesh_plink.c | 17 ++++++++++++++--- |
| 1 file changed, 14 insertions(+), 3 deletions(-) |
| |
| --- a/net/mac80211/mesh_plink.c |
| +++ b/net/mac80211/mesh_plink.c |
| @@ -412,7 +412,7 @@ void mesh_rx_plink_frame(struct ieee8021 |
| enum plink_event event; |
| enum plink_frame_type ftype; |
| size_t baselen; |
| - bool deactivated; |
| + bool deactivated, matches_local = true; |
| u8 ie_len; |
| u8 *baseaddr; |
| __le16 plid, llid, reason; |
| @@ -487,6 +487,7 @@ void mesh_rx_plink_frame(struct ieee8021 |
| /* Now we will figure out the appropriate event... */ |
| event = PLINK_UNDEFINED; |
| if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, sdata))) { |
| + matches_local = false; |
| switch (ftype) { |
| case PLINK_OPEN: |
| event = OPN_RJCT; |
| @@ -498,7 +499,15 @@ void mesh_rx_plink_frame(struct ieee8021 |
| /* avoid warning */ |
| break; |
| } |
| - spin_lock_bh(&sta->lock); |
| + } |
| + |
| + if (!sta && !matches_local) { |
| + rcu_read_unlock(); |
| + reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION); |
| + llid = 0; |
| + mesh_plink_frame_tx(sdata, PLINK_CLOSE, mgmt->sa, llid, |
| + plid, reason); |
| + return; |
| } else if (!sta) { |
| /* ftype == PLINK_OPEN */ |
| u32 rates; |
| @@ -522,7 +531,7 @@ void mesh_rx_plink_frame(struct ieee8021 |
| } |
| event = OPN_ACPT; |
| spin_lock_bh(&sta->lock); |
| - } else { |
| + } else if (matches_local) { |
| spin_lock_bh(&sta->lock); |
| switch (ftype) { |
| case PLINK_OPEN: |
| @@ -564,6 +573,8 @@ void mesh_rx_plink_frame(struct ieee8021 |
| rcu_read_unlock(); |
| return; |
| } |
| + } else { |
| + spin_lock_bh(&sta->lock); |
| } |
| |
| mpl_dbg("Mesh plink (peer, state, llid, plid, event): %pM %s %d %d %d\n", |