aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArend van Spriel <arend@broadcom.com>2012-11-14 21:46:10 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-11-16 14:28:50 -0500
commit607d5c0ef6c4d3a2e7a61ba1b62baa0712366bc0 (patch)
tree86e3e4f231959e19d1d4aaf2b1e9010a3b5a3ed8
parentbdf5ff516b453137cecb71e60ff860ec0a704509 (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.c66
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 */
198static void brcmf_fweh_queue_event(struct brcmf_if *ifp, 197static 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}