mmc: dw_mmc: Fix out-of-bounds access for slot's caps
authorShawn Lin <shawn.lin@rock-chips.com>
Sat, 24 Feb 2018 06:17:23 +0000 (14:17 +0800)
committerBen Hutchings <ben@decadent.org.uk>
Sat, 16 Jun 2018 21:22:28 +0000 (22:22 +0100)
commit 0d84b9e5631d923744767dc6608672df906dd092 upstream.

Add num_caps field for dw_mci_drv_data to validate the controller
id from DT alias and non-DT ways.

Reported-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
Fixes: 800d78bfccb3 ("mmc: dw_mmc: add support for implementation specific callbacks")
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
[bwh: Backported to 3.16:
 - Drop changes to dw_mmc-{k3,rockchip,zx}.c
 - Adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
drivers/mmc/host/dw_mmc-exynos.c
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/dw_mmc.h

index 0fbc53ac7eae8fb27f60b12575be4cabbe759c15..9bb46026b7da6a2cbd66a659885a3abe92a1f5a4 100644 (file)
@@ -394,6 +394,7 @@ static unsigned long exynos_dwmmc_caps[4] = {
 
 static const struct dw_mci_drv_data exynos_drv_data = {
        .caps                   = exynos_dwmmc_caps,
+       .num_caps               = ARRAY_SIZE(exynos_dwmmc_caps),
        .init                   = dw_mci_exynos_priv_init,
        .setup_clock            = dw_mci_exynos_setup_clock,
        .prepare_command        = dw_mci_exynos_prepare_command,
index c0a4812335bca0a4264b473708c445582a725781..6ddc7a187bf71ea21862d8f7892c57ca10b31b11 100644 (file)
@@ -2064,8 +2064,15 @@ static int dw_mci_init_slot_caps(struct dw_mci_slot *slot)
        } else {
                ctrl_id = to_platform_device(host->dev)->id;
        }
-       if (drv_data && drv_data->caps)
+
+       if (drv_data && drv_data->caps) {
+               if (ctrl_id >= drv_data->num_caps) {
+                       dev_err(host->dev, "invalid controller id %d\n",
+                               ctrl_id);
+                       return -EINVAL;
+               }
                mmc->caps |= drv_data->caps[ctrl_id];
+       }
 
        if (host->pdata->caps2)
                mmc->caps2 = host->pdata->caps2;
index 738fa241d05882258958107348a75b511c76fc08..8814666961c8a06e96f8f038249e03b95151a117 100644 (file)
@@ -237,6 +237,7 @@ struct dw_mci_tuning_data {
 /**
  * dw_mci driver data - dw-mshc implementation specific driver data.
  * @caps: mmc subsystem specified capabilities of the controller(s).
+ * @num_caps: number of capabilities specified by @caps.
  * @init: early implementation specific initialization.
  * @setup_clock: implementation specific clock configuration.
  * @prepare_command: handle CMD register extensions.
@@ -250,6 +251,7 @@ struct dw_mci_tuning_data {
  */
 struct dw_mci_drv_data {
        unsigned long   *caps;
+       u32             num_caps;
        int             (*init)(struct dw_mci *host);
        int             (*setup_clock)(struct dw_mci *host);
        void            (*prepare_command)(struct dw_mci *host, u32 *cmdr);