Commit aeecc574 authored by Arend van Spriel's avatar Arend van Spriel Committed by John W. Linville

brcmfmac: use skb_cow() in brcmf_sdbrcm_txpkt() to assure alignment

In brcmf_sdbrcm_txpkt() a new packet is allocated and used to transmit
to firmware freeing up the original packet. However, that packet is
still referenced in firmware-signalling so this would result in a
double free. Using skb_cow() avoids this as the packet reference is
unchanged.
Reviewed-by: default avatarHante Meuleman <meuleman@broadcom.com>
Reviewed-by: default avatarPiotr Haber <phaber@broadcom.com>
Reviewed-by: default avatarPieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent a0427809
...@@ -1781,7 +1781,6 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, ...@@ -1781,7 +1781,6 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
u8 *frame; u8 *frame;
u16 len, pad = 0; u16 len, pad = 0;
u32 swheader; u32 swheader;
struct sk_buff *new;
int i; int i;
brcmf_dbg(TRACE, "Enter\n"); brcmf_dbg(TRACE, "Enter\n");
...@@ -1795,26 +1794,14 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, ...@@ -1795,26 +1794,14 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
brcmf_dbg(INFO, "insufficient headroom %d for %d pad\n", brcmf_dbg(INFO, "insufficient headroom %d for %d pad\n",
skb_headroom(pkt), pad); skb_headroom(pkt), pad);
bus->sdiodev->bus_if->tx_realloc++; bus->sdiodev->bus_if->tx_realloc++;
new = brcmu_pkt_buf_get_skb(pkt->len + BRCMF_SDALIGN); ret = skb_cow(pkt, BRCMF_SDALIGN);
if (!new) { if (ret)
brcmf_err("couldn't allocate new %d-byte packet\n",
pkt->len + BRCMF_SDALIGN);
ret = -ENOMEM;
goto done; goto done;
} pad = ((unsigned long)frame % BRCMF_SDALIGN);
pkt_align(new, pkt->len, BRCMF_SDALIGN);
memcpy(new->data, pkt->data, pkt->len);
brcmu_pkt_buf_free_skb(pkt);
pkt = new;
frame = (u8 *) (pkt->data);
/* precondition: (frame % BRCMF_SDALIGN) == 0) */
pad = 0;
} else {
skb_push(pkt, pad);
frame = (u8 *) (pkt->data);
memset(frame + SDPCM_HDRLEN, 0, pad);
} }
skb_push(pkt, pad);
frame = (u8 *) (pkt->data);
memset(frame, 0, pad + SDPCM_HDRLEN);
} }
/* precondition: pad < BRCMF_SDALIGN */ /* precondition: pad < BRCMF_SDALIGN */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment