Date: Mon, 25 Oct 2010 11:43:05 +0200 From: Clemens Ladisch Subject: firewire: ohci: fix race when reading count in AR descriptor 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 Tested-by: Maxim Levitsky Signed-off-by: Stefan Richter --- drivers/firewire/ohci.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) Index: b/drivers/firewire/ohci.c =================================================================== --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -743,11 +743,13 @@ static void ar_context_tasklet(unsigned 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; @@ -815,7 +817,7 @@ static void ar_context_tasklet(unsigned } 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);