Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6

* 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6:
firewire: ohci: fix race when reading count in AR descriptor
firewire: ohci: avoid reallocation of AR buffers
firewire: ohci: fix race in AR split packet handling
firewire: ohci: fix buffer overflow in AR split packet handling

+65 -23
+65 -23
drivers/firewire/ohci.c
··· 577 577 return ret; 578 578 } 579 579 580 - static int ar_context_add_page(struct ar_context *ctx) 580 + static void ar_context_link_page(struct ar_context *ctx, 581 + struct ar_buffer *ab, dma_addr_t ab_bus) 581 582 { 582 - struct device *dev = ctx->ohci->card.device; 583 - struct ar_buffer *ab; 584 - dma_addr_t uninitialized_var(ab_bus); 585 583 size_t offset; 586 - 587 - ab = dma_alloc_coherent(dev, PAGE_SIZE, &ab_bus, GFP_ATOMIC); 588 - if (ab == NULL) 589 - return -ENOMEM; 590 584 591 585 ab->next = NULL; 592 586 memset(&ab->descriptor, 0, sizeof(ab->descriptor)); ··· 600 606 601 607 reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); 602 608 flush_writes(ctx->ohci); 609 + } 610 + 611 + static int ar_context_add_page(struct ar_context *ctx) 612 + { 613 + struct device *dev = ctx->ohci->card.device; 614 + struct ar_buffer *ab; 615 + dma_addr_t uninitialized_var(ab_bus); 616 + 617 + ab = dma_alloc_coherent(dev, PAGE_SIZE, &ab_bus, GFP_ATOMIC); 618 + if (ab == NULL) 619 + return -ENOMEM; 620 + 621 + ar_context_link_page(ctx, ab, ab_bus); 603 622 604 623 return 0; 605 624 } ··· 737 730 static void ar_context_tasklet(unsigned long data) 738 731 { 739 732 struct ar_context *ctx = (struct ar_context *)data; 740 - struct fw_ohci *ohci = ctx->ohci; 741 733 struct ar_buffer *ab; 742 734 struct descriptor *d; 743 735 void *buffer, *end; 736 + __le16 res_count; 744 737 745 738 ab = ctx->current_buffer; 746 739 d = &ab->descriptor; 747 740 748 - if (d->res_count == 0) { 749 - size_t size, rest, offset; 741 + res_count = ACCESS_ONCE(d->res_count); 742 + if (res_count == 0) { 743 + size_t size, size2, rest, pktsize, size3, offset; 750 744 dma_addr_t start_bus; 751 745 void *start; 752 746 ··· 758 750 */ 759 751 760 752 offset = offsetof(struct ar_buffer, data); 761 - start = buffer = ab; 753 + start = ab; 762 754 start_bus = le32_to_cpu(ab->descriptor.data_address) - offset; 755 + buffer = ab->data; 763 756 764 757 ab = ab->next; 765 758 d = &ab->descriptor; 766 - size = buffer + PAGE_SIZE - ctx->pointer; 759 + size = start + PAGE_SIZE - ctx->pointer; 760 + /* valid buffer data in the next page */ 767 761 rest = le16_to_cpu(d->req_count) - le16_to_cpu(d->res_count); 762 + /* what actually fits in this page */ 763 + size2 = min(rest, (size_t)PAGE_SIZE - offset - size); 768 764 memmove(buffer, ctx->pointer, size); 769 - memcpy(buffer + size, ab->data, rest); 770 - ctx->current_buffer = ab; 771 - ctx->pointer = (void *) ab->data + rest; 772 - end = buffer + size + rest; 765 + memcpy(buffer + size, ab->data, size2); 773 766 774 - while (buffer < end) 775 - buffer = handle_ar_packet(ctx, buffer); 767 + while (size > 0) { 768 + void *next = handle_ar_packet(ctx, buffer); 769 + pktsize = next - buffer; 770 + if (pktsize >= size) { 771 + /* 772 + * We have handled all the data that was 773 + * originally in this page, so we can now 774 + * continue in the next page. 775 + */ 776 + buffer = next; 777 + break; 778 + } 779 + /* move the next packet to the start of the buffer */ 780 + memmove(buffer, next, size + size2 - pktsize); 781 + size -= pktsize; 782 + /* fill up this page again */ 783 + size3 = min(rest - size2, 784 + (size_t)PAGE_SIZE - offset - size - size2); 785 + memcpy(buffer + size + size2, 786 + (void *) ab->data + size2, size3); 787 + size2 += size3; 788 + } 776 789 777 - dma_free_coherent(ohci->card.device, PAGE_SIZE, 778 - start, start_bus); 779 - ar_context_add_page(ctx); 790 + if (rest > 0) { 791 + /* handle the packets that are fully in the next page */ 792 + buffer = (void *) ab->data + 793 + (buffer - (start + offset + size)); 794 + end = (void *) ab->data + rest; 795 + 796 + while (buffer < end) 797 + buffer = handle_ar_packet(ctx, buffer); 798 + 799 + ctx->current_buffer = ab; 800 + ctx->pointer = end; 801 + 802 + ar_context_link_page(ctx, start, start_bus); 803 + } else { 804 + ctx->pointer = start + PAGE_SIZE; 805 + } 780 806 } else { 781 807 buffer = ctx->pointer; 782 808 ctx->pointer = end = 783 - (void *) ab + PAGE_SIZE - le16_to_cpu(d->res_count); 809 + (void *) ab + PAGE_SIZE - le16_to_cpu(res_count); 784 810 785 811 while (buffer < end) 786 812 buffer = handle_ar_packet(ctx, buffer);