* [PATCH] p54usb: fix nasty use after free
@ 2009-01-19 23:27 Christian Lamparter
2009-01-20 11:45 ` Artur Skawina
0 siblings, 1 reply; 3+ messages in thread
From: Christian Lamparter @ 2009-01-19 23:27 UTC (permalink / raw)
To: linux-wireless
Cc: John W. Linville, Artur Skawina, Larry Finger, Johannes Berg
In theory, the firmware acks the received a data frame, before signaling the driver to free it again.
However Artur Skawina <art.08.09@gmail.com> has shown that it can happen in reverse order as well.
This is very bad and could lead to memory corruptions, oopses and panics.
Thanks to Artur Skawina <art.08.09@gmail.com> for reporting and debugging this issue.
Signed-off-by: Christian Lamparter <chunkeey@web.de>
---
Anyone with a p54usb device (Especially you, Artur :-) ):
Please test this!
Because it should go to wireless-2.6 / 2.6.29 as well (John?)
Regards,
Chr
---
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index 3bfee58..364ef39 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -144,11 +144,8 @@ static void p54u_tx_cb(struct urb *urb)
struct sk_buff *skb = urb->context;
struct ieee80211_hw *dev = (struct ieee80211_hw *)
usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
- struct p54u_priv *priv = dev->priv;
- skb_pull(skb, priv->common.tx_hdr_len);
- if (FREE_AFTER_TX(skb))
- p54_free_skb(dev, skb);
+ p54_free_skb(dev, skb);
}
static void p54u_tx_dummy_cb(struct urb *urb) { }
@@ -230,7 +227,8 @@ static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb)
p54u_tx_dummy_cb, dev);
usb_fill_bulk_urb(data_urb, priv->udev,
usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
- skb->data, skb->len, p54u_tx_cb, skb);
+ skb->data, skb->len, FREE_AFTER_TX(skb) ?
+ p54u_tx_cb : p54u_tx_dummy_cb, skb);
usb_anchor_urb(addr_urb, &priv->submitted);
err = usb_submit_urb(addr_urb, GFP_ATOMIC);
@@ -269,28 +267,24 @@ static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb)
{
struct p54u_priv *priv = dev->priv;
struct urb *data_urb;
- struct lm87_tx_hdr *hdr;
- __le32 checksum;
- __le32 addr = ((struct p54_hdr *)skb->data)->req_id;
+ struct lm87_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr);
data_urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!data_urb)
return;
- checksum = p54u_lm87_chksum((__le32 *)skb->data, skb->len);
- hdr = (struct lm87_tx_hdr *)skb_push(skb, sizeof(*hdr));
- hdr->chksum = checksum;
- hdr->device_addr = addr;
+ hdr->chksum = p54u_lm87_chksum((__le32 *)skb->data, skb->len);
+ hdr->device_addr = ((struct p54_hdr *)skb->data)->req_id;
usb_fill_bulk_urb(data_urb, priv->udev,
usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
- skb->data, skb->len, p54u_tx_cb, skb);
+ hdr, skb->len + sizeof(*hdr), FREE_AFTER_TX(skb) ?
+ p54u_tx_cb : p54u_tx_dummy_cb, skb);
data_urb->transfer_flags |= URB_ZERO_PACKET;
usb_anchor_urb(data_urb, &priv->submitted);
if (usb_submit_urb(data_urb, GFP_ATOMIC)) {
usb_unanchor_urb(data_urb);
- skb_pull(skb, sizeof(*hdr));
p54_free_skb(dev, skb);
}
usb_free_urb(data_urb);
@@ -300,11 +294,9 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb)
{
struct p54u_priv *priv = dev->priv;
struct urb *int_urb, *data_urb;
- struct net2280_tx_hdr *hdr;
+ struct net2280_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr);
struct net2280_reg_write *reg;
int err = 0;
- __le32 addr = ((struct p54_hdr *) skb->data)->req_id;
- __le16 len = cpu_to_le16(skb->len);
reg = kmalloc(sizeof(*reg), GFP_ATOMIC);
if (!reg)
@@ -327,10 +319,9 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb)
reg->addr = cpu_to_le32(P54U_DEV_BASE);
reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);
- hdr = (void *)skb_push(skb, sizeof(*hdr));
memset(hdr, 0, sizeof(*hdr));
- hdr->len = len;
- hdr->device_addr = addr;
+ hdr->len = cpu_to_le16(skb->len);
+ hdr->device_addr = ((struct p54_hdr *) skb->data)->req_id;
usb_fill_bulk_urb(int_urb, priv->udev,
usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg),
@@ -345,7 +336,8 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb)
usb_fill_bulk_urb(data_urb, priv->udev,
usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
- skb->data, skb->len, p54u_tx_cb, skb);
+ hdr, skb->len + sizeof(*hdr), FREE_AFTER_TX(skb) ?
+ p54u_tx_cb : p54u_tx_dummy_cb, skb);
usb_anchor_urb(int_urb, &priv->submitted);
err = usb_submit_urb(int_urb, GFP_ATOMIC);
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH] p54usb: fix nasty use after free
2009-01-19 23:27 [PATCH] p54usb: fix nasty use after free Christian Lamparter
@ 2009-01-20 11:45 ` Artur Skawina
2009-01-20 12:12 ` Artur Skawina
0 siblings, 1 reply; 3+ messages in thread
From: Artur Skawina @ 2009-01-20 11:45 UTC (permalink / raw)
To: Christian Lamparter
Cc: linux-wireless, John W. Linville, Larry Finger, Johannes Berg
Christian Lamparter wrote:
> In theory, the firmware acks the received a data frame, before signaling the driver to free it again.
> However Artur Skawina <art.08.09@gmail.com> has shown that it can happen in reverse order as well.
> This is very bad and could lead to memory corruptions, oopses and panics.
>
> Thanks to Artur Skawina <art.08.09@gmail.com> for reporting and debugging this issue.
>
> Signed-off-by: Christian Lamparter <chunkeey@web.de>
> ---
> Anyone with a p54usb device (Especially you, Artur :-) ):
>
> Please test this!
> Because it should go to wireless-2.6 / 2.6.29 as well (John?)
good news: i've run a few tests w/ it and didn't see any memory corruption warnings,
previously i used to get them almost immediately, usually during association, now
i was able to transfer ~1M of data w/ no sign of corruption.
The large packet loss is still there and the device is still unusable (because of
the extremely low throughput, that 1M took several minutes to transfer and three
attempts to associate before it worked). But no crashes, that's a huge improvement :)
Tested-by: Artur Skawina <art.08.09@gmail.com>
artur
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] p54usb: fix nasty use after free
2009-01-20 11:45 ` Artur Skawina
@ 2009-01-20 12:12 ` Artur Skawina
0 siblings, 0 replies; 3+ messages in thread
From: Artur Skawina @ 2009-01-20 12:12 UTC (permalink / raw)
To: Artur Skawina
Cc: Christian Lamparter, linux-wireless, John W. Linville,
Larry Finger, Johannes Berg
> The large packet loss is still there and the device is still unusable (because of
> the extremely low throughput, that 1M took several minutes to transfer and three
> attempts to associate before it worked). But no crashes, that's a huge improvement :)
this turned out to be unrelated (URB_ZERO_PACKET on both urbs fixed it, but i need to do
more tests. note that w/o the equivalent of this patch URB_ZERO_PACKET didn't help).
artur
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2009-01-20 12:12 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-19 23:27 [PATCH] p54usb: fix nasty use after free Christian Lamparter
2009-01-20 11:45 ` Artur Skawina
2009-01-20 12:12 ` Artur Skawina
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).