lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date:   Fri, 24 Jul 2020 22:45:32 +0800
From:   Jia-Ju Bai <baijiaju@...nghua.edu.cn>
To:     3chas3@...il.com, linux-atm-general@...ts.sourceforge.net,
        doshir@...are.com, pv-drivers@...are.com, davem@...emloft.net,
        kuba@...nel.org, Greg KH <gregkh@...uxfoundation.org>
Cc:     netdev@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: Rule about streaming DMA mapping

Hello,

 From the book "Linux device drivers" (3rd edition), I find an 
interesting rule for streaming DMA mapping:

Once a buffer has been mapped, it belongs to the device, not the 
processor. Until
the buffer has been unmapped, the driver should not touch its contents 
in any
way. Only after dma_unmap_single has been called is it safe for the 
driver to
access the contents of the buffer (with one exception that we see shortly).
Among other things, this rule implies that a buffer being written to a 
device cannot
be mapped until it contains all the data to write.

I find some violations about this rule, and there are two examples in 
Linux-5.6:

=== EXAMPLE 1 ===
In vmxnet3_probe_device() in drivers/net/vmxnet3/vmxnet3_drv.c:
     adapter->adapter_pa = dma_map_single(&adapter->pdev->dev, adapter,
                          sizeof(struct vmxnet3_adapter),
                          PCI_DMA_TODEVICE);
     if (dma_mapping_error(&adapter->pdev->dev, adapter->adapter_pa)) {
         dev_err(&pdev->dev, "Failed to map dma\n");
         err = -EFAULT;
         goto err_set_mask;
     }
     adapter->shared = dma_alloc_coherent(
                 &adapter->pdev->dev,
                 sizeof(struct Vmxnet3_DriverShared),
                 &adapter->shared_pa, GFP_KERNEL);
     if (!adapter->shared) {
         dev_err(&pdev->dev, "Failed to allocate memory\n");
         err = -ENOMEM;
         goto err_alloc_shared;
     }

     adapter->num_rx_queues = num_rx_queues;
     adapter->num_tx_queues = num_tx_queues;
     adapter->rx_buf_per_pkt = 1;

The variable "adapter" is mapped to streaming DMA, but its fields are 
used before this variable is unmapped.

=== EXAMPLE 2 ===
In queue_skb() in drivers/atm/idt77252.c:
     IDT77252_PRV_PADDR(skb) = dma_map_single(&card->pcidev->dev, skb->data,
                          skb->len, DMA_TO_DEVICE);

     error = -EINVAL;

     if (oam) {
         if (skb->len != 52)
             goto errout;

         tbd->word_1 = SAR_TBD_OAM | ATM_CELL_PAYLOAD | SAR_TBD_EPDU;
         tbd->word_2 = IDT77252_PRV_PADDR(skb) + 4;
         tbd->word_3 = 0x00000000;
         tbd->word_4 = (skb->data[0] << 24) | (skb->data[1] << 16) |
                   (skb->data[2] <<  8) | (skb->data[3] <<  0);

The array "skb->data" is mapped to streaming DMA, but its elements are 
used before this array is unmapped.

Because I am not familiar with streaming DMA mapping, I wonder whether 
these violations are real?
If they are real, what problems can they cause?

Thanks a lot :)


Best wishes,
Jia-Ju Bai

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ