Skip to content

Commit

Permalink
firewire: ohci: fix race when reading count in AR descriptor
Browse files Browse the repository at this point in the history
If the controller is storing a split packet and therefore changing
d->res_count to zero between the two reads by the driver, we end up with
an end pointer that is not at a packet boundary, and therefore overflow
the buffer when handling the split packet.

To fix this, read the field once, atomically.  The compiler usually
merges the two reads anyway, but for correctness, we have to enforce it.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Tested-by: Maxim Levitsky <maximlevitsky@gmail.com>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
  • Loading branch information
Clemens Ladisch authored and Stefan Richter committed Oct 30, 2010
1 parent 837596a commit 693fa77
Showing 1 changed file with 4 additions and 2 deletions.
6 changes: 4 additions & 2 deletions drivers/firewire/ohci.c
Original file line number Diff line number Diff line change
Expand Up @@ -740,11 +740,13 @@ static void ar_context_tasklet(unsigned long data)
struct ar_buffer *ab;
struct descriptor *d;
void *buffer, *end;
__le16 res_count;

ab = ctx->current_buffer;
d = &ab->descriptor;

if (d->res_count == 0) {
res_count = ACCESS_ONCE(d->res_count);
if (res_count == 0) {
size_t size, size2, rest, pktsize, size3, offset;
dma_addr_t start_bus;
void *start;
Expand Down Expand Up @@ -812,7 +814,7 @@ static void ar_context_tasklet(unsigned long data)
} else {
buffer = ctx->pointer;
ctx->pointer = end =
(void *) ab + PAGE_SIZE - le16_to_cpu(d->res_count);
(void *) ab + PAGE_SIZE - le16_to_cpu(res_count);

while (buffer < end)
buffer = handle_ar_packet(ctx, buffer);
Expand Down

0 comments on commit 693fa77

Please sign in to comment.