diff options
author | Arend van Spriel <arend@broadcom.com> | 2012-11-14 21:46:10 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-11-16 14:28:50 -0500 |
commit | 607d5c0ef6c4d3a2e7a61ba1b62baa0712366bc0 (patch) | |
tree | 86e3e4f231959e19d1d4aaf2b1e9010a3b5a3ed8 | |
parent | bdf5ff516b453137cecb71e60ff860ec0a704509 (diff) |
brcmfmac: correct handling IF firmware event
Testing revealed the IF ADD event contains the interface
index of the new interface. This would result in a NULL
pointer access when handling the event.
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Franky Lin <frankyl@broadcom.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/fweh.c | 66 |
1 files changed, 31 insertions, 35 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c index 825be26b0c65..e1521afe6522 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c | |||
@@ -191,42 +191,13 @@ static const char *brcmf_fweh_event_name(enum brcmf_fweh_event_code code) | |||
191 | /** | 191 | /** |
192 | * brcmf_fweh_queue_event() - create and queue event. | 192 | * brcmf_fweh_queue_event() - create and queue event. |
193 | * | 193 | * |
194 | * @ifp: firmware interface object. | 194 | * @fweh: firmware event handling info. |
195 | * @code: event code. | 195 | * @event: event queue entry. |
196 | * @pkt: event ether packet. | ||
197 | */ | 196 | */ |
198 | static void brcmf_fweh_queue_event(struct brcmf_if *ifp, | 197 | static void brcmf_fweh_queue_event(struct brcmf_fweh_info *fweh, |
199 | enum brcmf_fweh_event_code code, | 198 | struct brcmf_fweh_queue_item *event) |
200 | struct brcmf_event *pkt) | ||
201 | { | 199 | { |
202 | struct brcmf_fweh_info *fweh = &ifp->drvr->fweh; | ||
203 | struct brcmf_fweh_queue_item *event; | ||
204 | gfp_t alloc_flag = GFP_KERNEL; | ||
205 | ulong flags; | 200 | ulong flags; |
206 | void *data; | ||
207 | u32 datalen; | ||
208 | |||
209 | /* determine event data */ | ||
210 | datalen = get_unaligned_be32(&pkt->msg.datalen); | ||
211 | data = &pkt[1]; | ||
212 | |||
213 | if (!ifp->ndev || (code != BRCMF_E_IF && !fweh->evt_handler[code])) { | ||
214 | brcmf_dbg(EVENT, "event ignored: code=%d\n", code); | ||
215 | brcmf_dbg_hex_dump(BRCMF_EVENT_ON(), data, datalen, "event:"); | ||
216 | return; | ||
217 | } | ||
218 | |||
219 | if (in_interrupt()) | ||
220 | alloc_flag = GFP_ATOMIC; | ||
221 | |||
222 | event = kzalloc(sizeof(*event) + datalen, alloc_flag); | ||
223 | event->code = code; | ||
224 | event->ifidx = ifp->idx; | ||
225 | |||
226 | /* use memcpy to get aligned event message */ | ||
227 | memcpy(&event->emsg, &pkt->msg, sizeof(event->emsg)); | ||
228 | memcpy(event->data, data, datalen); | ||
229 | memcpy(event->ifaddr, pkt->eth.h_dest, ETH_ALEN); | ||
230 | 201 | ||
231 | spin_lock_irqsave(&fweh->evt_q_lock, flags); | 202 | spin_lock_irqsave(&fweh->evt_q_lock, flags); |
232 | list_add_tail(&event->q, &fweh->event_q); | 203 | list_add_tail(&event->q, &fweh->event_q); |
@@ -489,10 +460,35 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr, | |||
489 | struct brcmf_event *event_packet, u8 *ifidx) | 460 | struct brcmf_event *event_packet, u8 *ifidx) |
490 | { | 461 | { |
491 | enum brcmf_fweh_event_code code; | 462 | enum brcmf_fweh_event_code code; |
463 | struct brcmf_fweh_info *fweh = &drvr->fweh; | ||
464 | struct brcmf_fweh_queue_item *event; | ||
465 | gfp_t alloc_flag = GFP_KERNEL; | ||
466 | void *data; | ||
467 | u32 datalen; | ||
492 | 468 | ||
493 | /* determine event code and interface index */ | 469 | /* get event info */ |
494 | code = get_unaligned_be32(&event_packet->msg.event_type); | 470 | code = get_unaligned_be32(&event_packet->msg.event_type); |
471 | datalen = get_unaligned_be32(&event_packet->msg.datalen); | ||
495 | *ifidx = event_packet->msg.ifidx; | 472 | *ifidx = event_packet->msg.ifidx; |
473 | data = &event_packet[1]; | ||
474 | |||
475 | if (code != BRCMF_E_IF && !fweh->evt_handler[code]) { | ||
476 | brcmf_dbg(EVENT, "event ignored: code=%d\n", code); | ||
477 | brcmf_dbg_hex_dump(BRCMF_EVENT_ON(), data, datalen, "event:"); | ||
478 | return; | ||
479 | } | ||
480 | |||
481 | if (in_interrupt()) | ||
482 | alloc_flag = GFP_ATOMIC; | ||
483 | |||
484 | event = kzalloc(sizeof(*event) + datalen, alloc_flag); | ||
485 | event->code = code; | ||
486 | event->ifidx = *ifidx; | ||
487 | |||
488 | /* use memcpy to get aligned event message */ | ||
489 | memcpy(&event->emsg, &event_packet->msg, sizeof(event->emsg)); | ||
490 | memcpy(event->data, data, datalen); | ||
491 | memcpy(event->ifaddr, event_packet->eth.h_dest, ETH_ALEN); | ||
496 | 492 | ||
497 | brcmf_fweh_queue_event(drvr->iflist[*ifidx], code, event_packet); | 493 | brcmf_fweh_queue_event(fweh, event); |
498 | } | 494 | } |