aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux
diff options
context:
space:
mode:
authorAndré Draszik <git@andred.net>2018-02-22 10:21:46 +0000
committerMathias Kresin <dev@kresin.me>2018-04-04 08:29:17 +0200
commitace16862006efd4ce025bf54997cdb20584d0fe4 (patch)
tree4f54b9c9ffe073a92c1367447e806c85adca0c15 /target/linux
parentdcbf6284e58e76111e8fa1c93ffd93c378e3482d (diff)
downloadupstream-ace16862006efd4ce025bf54997cdb20584d0fe4.tar.gz
upstream-ace16862006efd4ce025bf54997cdb20584d0fe4.tar.bz2
upstream-ace16862006efd4ce025bf54997cdb20584d0fe4.zip
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@andred.net>
Diffstat (limited to 'target/linux')
-rw-r--r--target/linux/ramips/patches-4.14/0046-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch6
-rw-r--r--target/linux/ramips/patches-4.9/0046-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch6
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 aad6d598e0..ef162d7acf 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@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@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 7dd25b1d40..da3c0772b5 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@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@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;