]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
atm: idt77252: avoid accessing the data mapped to streaming DMA
authorJia-Ju Bai <baijiaju@tsinghua.edu.cn>
Sun, 2 Aug 2020 09:33:40 +0000 (17:33 +0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 3 Aug 2020 22:51:25 +0000 (15:51 -0700)
In queue_skb(), skb->data is mapped to streaming DMA on line 850:
  dma_map_single(..., skb->data, ...);

Then skb->data is accessed on lines 862 and 863:
  tbd->word_4 = (skb->data[0] << 24) | (skb->data[1] << 16) |
           (skb->data[2] <<  8) | (skb->data[3] <<  0);
and on lines 893 and 894:
  tbd->word_4 = (skb->data[0] << 24) | (skb->data[1] << 16) |
           (skb->data[2] <<  8) | (skb->data[3] <<  0);

These accesses may cause data inconsistency between CPU cache and
hardware.

To fix this problem, the calculation result of skb->data is stored in a
local variable before DMA mapping, and then the driver accesses this
local variable instead of skb->data.

Signed-off-by: Jia-Ju Bai <baijiaju@tsinghua.edu.cn>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/atm/idt77252.c

index df51680e89319c44fb904dd1f0d9635a4e1eb4cb..65a3886f68c9e391722b99d0ebe4d45fc3de7fe9 100644 (file)
@@ -835,6 +835,7 @@ queue_skb(struct idt77252_dev *card, struct vc_map *vc,
        unsigned long flags;
        int error;
        int aal;
+       u32 word4;
 
        if (skb->len == 0) {
                printk("%s: invalid skb->len (%d)\n", card->name, skb->len);
@@ -846,6 +847,8 @@ queue_skb(struct idt77252_dev *card, struct vc_map *vc,
 
        tbd = &IDT77252_PRV_TBD(skb);
        vcc = ATM_SKB(skb)->vcc;
+       word4 = (skb->data[0] << 24) | (skb->data[1] << 16) |
+                       (skb->data[2] <<  8) | (skb->data[3] <<  0);
 
        IDT77252_PRV_PADDR(skb) = dma_map_single(&card->pcidev->dev, skb->data,
                                                 skb->len, DMA_TO_DEVICE);
@@ -859,8 +862,7 @@ queue_skb(struct idt77252_dev *card, struct vc_map *vc,
                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);
+               tbd->word_4 = word4;
 
                if (test_bit(VCF_RSV, &vc->flags))
                        vc = card->vcs[0];
@@ -890,8 +892,7 @@ queue_skb(struct idt77252_dev *card, struct vc_map *vc,
 
                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);
+               tbd->word_4 = word4;
                break;
 
        case ATM_AAL5: