[openwrt/openwrt] uboot-lantiq: fix out of bounds cache invalidate

LEDE Commits lede-commits at lists.infradead.org
Sun Nov 14 11:22:57 PST 2021


mkresin pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/87b8f095af9f7e6ff5edae6778d967f91e779cf2

commit 87b8f095af9f7e6ff5edae6778d967f91e779cf2
Author: Mathias Kresin <dev at kresin.me>
AuthorDate: Tue Nov 2 22:20:28 2021 +0100

    uboot-lantiq: fix out of bounds cache invalidate
    
    With gcc10 the variables are placed more tightly to each other, which
    uncovers a long existing bug in the lantiq DMA code. It can be observed
    when using tftpboot with the filename parameter, which gets reset during
    the tftpboot execution.
    
    NetRxPackets[] points to cache line size aligned addresses. In
    ltq_eth_rx_packet_align() the address NetRxPackets[] points to is
    increased by LTQ_ETH_IP_ALIGN and the resulting not cache aligned
    address is used further on. While doing so, the length/size is never
    updated.
    
    The "not cache aligned address" + len/size for a cache aligned address
    is passed to invalidate_dcache_range(). Hence, invalidate_dcache_range()
    invalidates the next 32 bit as well, which flashes the BootFile variable
    as well.
    
       variable BootFile is at address: 0x83ffe12c
       NetRxPackets[] points to 0x83ffdb20 (len is 0x600)
       data points to: 0x83ffdb22 (len is 0x600)
    
       ltq_dma_dcache_inv: 0x83ffdb22 (for len 0x600)
       invalidate_dcache_range: 0x83ffdb20 to 0x83ffe120 (size: 32)
       invalidate_dcache_range: 0x83ffdb20 to 0x83ffdb40 (Bootfile: a.bin)
       ...
       invalidate_dcache_range: 0x83ffe100 to 0x83ffe120 (Bootfile: a.bin)
       invalidate_dcache_range: 0x83ffe120 to 0x83ffe140 (Bootfile: )
    
    In ltq_dma_tx_map() and ltq_dma_rx_map() the start address passed to
    ltq_dma_dcache_wb_inv() is incorrect. By considering the offset, the
    start address passed to flush_dcache_range() is always aligned to 32, 64
    or 128 bytes dependent on configured DMA burst size.
    
    Fixes: FS#4113
    
    Signed-off-by: Mathias Kresin <dev at kresin.me>
---
 ...lantiq-fix-out-of-bounds-cache-invalidate.patch | 62 ++++++++++++++++++++++
 1 file changed, 62 insertions(+)

diff --git a/package/boot/uboot-lantiq/patches/0031-dma-lantiq-fix-out-of-bounds-cache-invalidate.patch b/package/boot/uboot-lantiq/patches/0031-dma-lantiq-fix-out-of-bounds-cache-invalidate.patch
new file mode 100644
index 0000000000..b99b07292c
--- /dev/null
+++ b/package/boot/uboot-lantiq/patches/0031-dma-lantiq-fix-out-of-bounds-cache-invalidate.patch
@@ -0,0 +1,62 @@
+From d9527989b2d63749d6c6678fa3a1b658eb26c225 Mon Sep 17 00:00:00 2001
+From: Mathias Kresin <dev at kresin.me>
+Date: Tue, 2 Nov 2021 21:24:29 +0100
+Subject: [PATCH] dma: lantiq: fix out of bounds cache invalidate
+
+With gcc10 the variables are placed more tightly to each other, which
+uncovers a long existing bug in the lantiq DMA code. It can be observed
+when using tftpboot with the filename parameter, which gets reset during
+the tftpboot execution.
+
+NetRxPackets[] points to cache line size aligned addresses. In
+ltq_eth_rx_packet_align() the address NetRxPackets[] points to is
+increased by LTQ_ETH_IP_ALIGN and the resulting not cache aligned
+address is used further on. While doing so, the length/size is never
+updated.
+
+The "not cache aligned address" + len/size for a cache aligned address
+is passed to invalidate_dcache_range(). Hence, invalidate_dcache_range()
+invalidates the next 32 bit as well, which flashes the BootFile variable
+as well.
+
+   variable BootFile is at address: 0x83ffe12c
+   NetRxPackets[] points to 0x83ffdb20 (len is 0x600)
+   data points to: 0x83ffdb22 (len is 0x600)
+
+   ltq_dma_dcache_inv: 0x83ffdb22 (for len 0x600)
+   invalidate_dcache_range: 0x83ffdb20 to 0x83ffe120 (size: 32)
+   invalidate_dcache_range: 0x83ffdb20 to 0x83ffdb40 (Bootfile: a.bin)
+   ...
+   invalidate_dcache_range: 0x83ffe100 to 0x83ffe120 (Bootfile: a.bin)
+   invalidate_dcache_range: 0x83ffe120 to 0x83ffe140 (Bootfile: )
+
+In ltq_dma_tx_map() and ltq_dma_rx_map() the start address passed to
+ltq_dma_dcache_wb_inv() is incorrect. By considering the offset, the
+start address passed to flush_dcache_range() is always aligned to 32, 64
+or 128 bytes dependent on configured DMA burst size.
+
+Signed-off-by: Mathias Kresin <dev at kresin.me>
+---
+ drivers/dma/lantiq_dma.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/dma/lantiq_dma.c
++++ b/drivers/dma/lantiq_dma.c
+@@ -280,7 +280,7 @@ int ltq_dma_rx_map(struct ltq_dma_device
+ 
+ 	offset = dma_addr % ltq_dma_burst_align(dev->rx_burst_len);
+ 
+-	ltq_dma_dcache_inv(data, len);
++	ltq_dma_dcache_inv(data - offset, len);
+ 
+ #if 0
+ 	printf("%s: index %d, data %p, dma_addr %08x, offset %u, len %d\n",
+@@ -355,7 +355,7 @@ int ltq_dma_tx_map(struct ltq_dma_device
+ 		__func__, index, desc, data, dma_addr, offset, len);
+ #endif
+ 
+-	ltq_dma_dcache_wb_inv(data, len);
++	ltq_dma_dcache_wb_inv(data - offset, len);
+ 
+ 	desc->addr = dma_addr - offset;
+ 	desc->ctl = DMA_DESC_OWN | DMA_DESC_SOP | DMA_DESC_EOP |



More information about the lede-commits mailing list