This is a note to let you know that I've just added the patch titled
firewire: ohci: fix buffer overflow in AR split packet handling
to the 2.6.36-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
firewire-ohci-fix-buffer-overflow-in-ar-split-packet-handling.patch
and it can be found in the queue-2.6.36 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree,
please let <[email protected]> know about it.
>From 85f7ffd5d2b320f73912b15fe8cef34bae297daf Mon Sep 17 00:00:00 2001
From: Clemens Ladisch <[email protected]>
Date: Mon, 25 Oct 2010 11:41:53 +0200
Subject: firewire: ohci: fix buffer overflow in AR split packet handling
From: Clemens Ladisch <[email protected]>
commit 85f7ffd5d2b320f73912b15fe8cef34bae297daf upstream.
When the controller had to split a received asynchronous packet into two
buffers, the driver tries to reassemble it by copying both parts into
the first page. However, if size + rest > PAGE_SIZE, i.e., if the yet
unhandled packets before the split packet, the split packet itself, and
any received packets after the split packet are together larger than one
page, then the memory after the first page would get overwritten.
To fix this, do not try to copy the data of all unhandled packets at
once, but copy the possibly needed data every time when handling
a packet.
This gets rid of most of the infamous crashes and data corruptions when
using firewire-net.
Signed-off-by: Clemens Ladisch <[email protected]>
Tested-by: Maxim Levitsky <[email protected]>
Signed-off-by: Stefan Richter <[email protected]> (cast PAGE_SIZE to
size_t)
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
drivers/firewire/ohci.c | 35 ++++++++++++++++++++++++++++++++---
1 file changed, 32 insertions(+), 3 deletions(-)
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -739,7 +739,7 @@ static void ar_context_tasklet(unsigned
d = &ab->descriptor;
if (d->res_count == 0) {
- size_t size, rest, offset;
+ size_t size, size2, rest, pktsize, size3, offset;
dma_addr_t start_bus;
void *start;
@@ -756,12 +756,41 @@ static void ar_context_tasklet(unsigned
ab = ab->next;
d = &ab->descriptor;
size = buffer + PAGE_SIZE - ctx->pointer;
+ /* valid buffer data in the next page */
rest = le16_to_cpu(d->req_count) - le16_to_cpu(d->res_count);
+ /* what actually fits in this page */
+ size2 = min(rest, (size_t)PAGE_SIZE - size);
memmove(buffer, ctx->pointer, size);
- memcpy(buffer + size, ab->data, rest);
+ memcpy(buffer + size, ab->data, size2);
ctx->current_buffer = ab;
ctx->pointer = (void *) ab->data + rest;
- end = buffer + size + rest;
+
+ while (size > 0) {
+ void *next = handle_ar_packet(ctx, buffer);
+ pktsize = next - buffer;
+ if (pktsize >= size) {
+ /*
+ * We have handled all the data that was
+ * originally in this page, so we can now
+ * continue in the next page.
+ */
+ buffer = next;
+ break;
+ }
+ /* move the next packet to the start of the buffer */
+ memmove(buffer, next, size + size2 - pktsize);
+ size -= pktsize;
+ /* fill up this page again */
+ size3 = min(rest - size2,
+ (size_t)PAGE_SIZE - size - size2);
+ memcpy(buffer + size + size2,
+ (void *) ab->data + size2, size3);
+ size2 += size3;
+ }
+
+ /* handle the packets that are fully in the next page */
+ buffer = (void *) ab->data + (buffer - (start + size));
+ end = (void *) ab->data + rest;
while (buffer < end)
buffer = handle_ar_packet(ctx, buffer);
Patches currently in stable-queue which might be from [email protected] are
queue-2.6.36/firewire-ohci-fix-race-in-ar-split-packet-handling.patch
queue-2.6.36/hpet-fix-unwanted-interrupt-due-to-stale-irq-status-bit.patch
queue-2.6.36/hpet-unmap-unused-i-o-space.patch
queue-2.6.36/firewire-ohci-fix-buffer-overflow-in-ar-split-packet-handling.patch
_______________________________________________
stable mailing list
[email protected]
http://linux.kernel.org/mailman/listinfo/stable