lkml.org 
[lkml]   [2020]   [May]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.6 136/194] usb: usbfs: correct kernel->user page attribute mismatch
    Date
    From: Jeremy Linton <jeremy.linton@arm.com>

    commit 2bef9aed6f0e22391c8d4570749b1acc9bc3981e upstream.

    On some architectures (e.g. arm64) requests for
    IO coherent memory may use non-cachable attributes if
    the relevant device isn't cache coherent. If these
    pages are then remapped into userspace as cacheable,
    they may not be coherent with the non-cacheable mappings.

    In particular this happens with libusb, when it attempts
    to create zero-copy buffers for use by rtl-sdr
    (https://github.com/osmocom/rtl-sdr/). On low end arm
    devices with non-coherent USB ports, the application will
    be unexpectedly killed, while continuing to work fine on
    arm machines with coherent USB controllers.

    This bug has been discovered/reported a few times over
    the last few years. In the case of rtl-sdr a compile time
    option to enable/disable zero copy was implemented to
    work around it.

    Rather than relaying on application specific workarounds,
    dma_mmap_coherent() can be used instead of remap_pfn_range().
    The page cache/etc attributes will then be correctly set in
    userspace to match the kernel mapping.

    Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
    Cc: stable <stable@vger.kernel.org>
    Link: https://lore.kernel.org/r/20200504201348.1183246-1-jeremy.linton@arm.com
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/usb/core/devio.c | 5 ++---
    1 file changed, 2 insertions(+), 3 deletions(-)

    --- a/drivers/usb/core/devio.c
    +++ b/drivers/usb/core/devio.c
    @@ -217,6 +217,7 @@ static int usbdev_mmap(struct file *file
    {
    struct usb_memory *usbm = NULL;
    struct usb_dev_state *ps = file->private_data;
    + struct usb_hcd *hcd = bus_to_hcd(ps->dev->bus);
    size_t size = vma->vm_end - vma->vm_start;
    void *mem;
    unsigned long flags;
    @@ -250,9 +251,7 @@ static int usbdev_mmap(struct file *file
    usbm->vma_use_count = 1;
    INIT_LIST_HEAD(&usbm->memlist);

    - if (remap_pfn_range(vma, vma->vm_start,
    - virt_to_phys(usbm->mem) >> PAGE_SHIFT,
    - size, vma->vm_page_prot) < 0) {
    + if (dma_mmap_coherent(hcd->self.sysdev, vma, mem, dma_handle, size)) {
    dec_usb_memory_use_count(usbm, &usbm->vma_use_count);
    return -EAGAIN;
    }

    \
     
     \ /
      Last update: 2020-05-18 20:06    [W:4.038 / U:0.276 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site