[openwrt/openwrt] ramips: mt7620: eMMC: stop invalid memory access if only one device is defined

LEDE Commits lede-commits at lists.infradead.org
Wed Apr 4 00:16:29 PDT 2018


mkresin pushed a commit to openwrt/openwrt.git, branch master:
https://git.lede-project.org/ace16862006efd4ce025bf54997cdb20584d0fe4

commit ace16862006efd4ce025bf54997cdb20584d0fe4
Author: André Draszik <git at andred.net>
AuthorDate: Thu Feb 22 10:21:46 2018 +0000

    ramips: mt7620: eMMC: stop invalid memory access if only one device is defined
    
    pdev->id is -1 when only one device exists, and is used:
    * as an index into drv_mode[] to determine whether to use
      PIO or DMA mode (via host->id)
    * as an index into msdc_6575_host[], to store the
      mmc_priv() data.
    
    Obviously, -1 is not a valid index in either case, causing
    us to read invalid memory, and memory corruption,
    respectively.
    
    The invalid memory read is causing non-deterministic
    behaviour, in particular in the v4.4 kernel it still
    picked DMA mode, but in the v4.9 it now always picks
    PIO mode.
    Also, PIO mode doesn't work, causing the following:
    
    / # echo 3 > /proc/sys/vm/drop_caches
    [ 3845.249237] sh (128): drop_caches: 3
    
    / # /root/usr/lib/libc.so
    [ 3846.096070] do_page_fault(): sending SIGSEGV to libc.so for invalid read access from 7f9cb5a0
    [ 3846.104758] epc = 779b0ea4 in libc.so[7792f000+c3000]
    [ 3846.109907] ra  = 779a8004 in libc.so[7792f000+c3000]
    Segmentation fault
    
    / # /root/usr/lib/libc.so
    musl libc (mipsel-sf)
    Version 1.1.16-git-40-g54807d47
    Dynamic Program Loader
    Usage: /root/usr/lib/libc.so [options] [--] pathname [args]
    
    (i.e. initial page-in of any binary causes a segfault,
    subsequent access works.)
    
    While this change doesn't fix PIO mode, it at least makes
    us deterministically use DMA (which works), and it also
    stops us from corrupting memory.
    
    Signed-off-by: André Draszik <git at andred.net>
---
 .../0046-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch            | 6 ++++--
 .../0046-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch            | 6 ++++--
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/target/linux/ramips/patches-4.14/0046-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch b/target/linux/ramips/patches-4.14/0046-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch
index aad6d59..ef162d7 100644
--- a/target/linux/ramips/patches-4.14/0046-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch
+++ b/target/linux/ramips/patches-4.14/0046-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch
@@ -1761,7 +1761,7 @@ Signed-off-by: John Crispin <blogic at openwrt.org>
 +
 --- /dev/null
 +++ b/drivers/mmc/host/mtk-mmc/sd.c
-@@ -0,0 +1,3066 @@
+@@ -0,0 +1,3068 @@
 +/* Copyright Statement:
 + *
 + * This software/firmware and related documentation ("MediaTek Software") are
@@ -4572,7 +4572,9 @@ Signed-off-by: John Crispin <blogic at openwrt.org>
 +    host = mmc_priv(mmc);
 +    host->hw        = hw;
 +    host->mmc       = mmc;
-+    host->id        = pdev->id;
++    BUG_ON(pdev->id < -1);
++    BUG_ON(pdev->id >= ARRAY_SIZE(drv_mode));
++    host->id        = (pdev->id == -1) ? 0 : pdev->id;
 +    host->error     = 0;
 +    host->irq       = irq;    
 +    host->base      = (unsigned long) base;
diff --git a/target/linux/ramips/patches-4.9/0046-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch b/target/linux/ramips/patches-4.9/0046-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch
index 7dd25b1..da3c077 100644
--- a/target/linux/ramips/patches-4.9/0046-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch
+++ b/target/linux/ramips/patches-4.9/0046-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch
@@ -1761,7 +1761,7 @@ Signed-off-by: John Crispin <blogic at openwrt.org>
 +
 --- /dev/null
 +++ b/drivers/mmc/host/mtk-mmc/sd.c
-@@ -0,0 +1,3066 @@
+@@ -0,0 +1,3068 @@
 +/* Copyright Statement:
 + *
 + * This software/firmware and related documentation ("MediaTek Software") are
@@ -4572,7 +4572,9 @@ Signed-off-by: John Crispin <blogic at openwrt.org>
 +    host = mmc_priv(mmc);
 +    host->hw        = hw;
 +    host->mmc       = mmc;
-+    host->id        = pdev->id;
++    BUG_ON(pdev->id < -1);
++    BUG_ON(pdev->id >= ARRAY_SIZE(drv_mode));
++    host->id        = (pdev->id == -1) ? 0 : pdev->id;
 +    host->error     = 0;
 +    host->irq       = irq;    
 +    host->base      = (unsigned long) base;



More information about the lede-commits mailing list