[PATCH 4.14 019/110] mmc: dw_mmc: Fix out-of-bounds access for slots caps

2018-03-07 Thread Greg Kroah-Hartman
4.14-stable review patch.  If anyone has any objections, please let me know.

--

From: Shawn Lin 

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 
Signed-off-by: Shawn Lin 
Fixes: 800d78bfccb3 ("mmc: dw_mmc: add support for implementation specific 
callbacks")
Cc: 
Signed-off-by: Ulf Hansson 
Signed-off-by: Greg Kroah-Hartman 

---
 drivers/mmc/host/dw_mmc-exynos.c   |1 +
 drivers/mmc/host/dw_mmc-k3.c   |1 +
 drivers/mmc/host/dw_mmc-rockchip.c |1 +
 drivers/mmc/host/dw_mmc-zx.c   |1 +
 drivers/mmc/host/dw_mmc.c  |9 -
 drivers/mmc/host/dw_mmc.h  |2 ++
 6 files changed, 14 insertions(+), 1 deletion(-)

--- a/drivers/mmc/host/dw_mmc-exynos.c
+++ b/drivers/mmc/host/dw_mmc-exynos.c
@@ -487,6 +487,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,
.set_ios= dw_mci_exynos_set_ios,
.parse_dt   = dw_mci_exynos_parse_dt,
--- a/drivers/mmc/host/dw_mmc-k3.c
+++ b/drivers/mmc/host/dw_mmc-k3.c
@@ -210,6 +210,7 @@ static int dw_mci_hi6220_execute_tuning(
 
 static const struct dw_mci_drv_data hi6220_data = {
.caps   = dw_mci_hi6220_caps,
+   .num_caps   = ARRAY_SIZE(dw_mci_hi6220_caps),
.switch_voltage = dw_mci_hi6220_switch_voltage,
.set_ios= dw_mci_hi6220_set_ios,
.parse_dt   = dw_mci_hi6220_parse_dt,
--- a/drivers/mmc/host/dw_mmc-rockchip.c
+++ b/drivers/mmc/host/dw_mmc-rockchip.c
@@ -319,6 +319,7 @@ static const struct dw_mci_drv_data rk29
 
 static const struct dw_mci_drv_data rk3288_drv_data = {
.caps   = dw_mci_rk3288_dwmmc_caps,
+   .num_caps   = ARRAY_SIZE(dw_mci_rk3288_dwmmc_caps),
.set_ios= dw_mci_rk3288_set_ios,
.execute_tuning = dw_mci_rk3288_execute_tuning,
.parse_dt   = dw_mci_rk3288_parse_dt,
--- a/drivers/mmc/host/dw_mmc-zx.c
+++ b/drivers/mmc/host/dw_mmc-zx.c
@@ -195,6 +195,7 @@ static unsigned long zx_dwmmc_caps[3] =
 
 static const struct dw_mci_drv_data zx_drv_data = {
.caps   = zx_dwmmc_caps,
+   .num_caps   = ARRAY_SIZE(zx_dwmmc_caps),
.execute_tuning = dw_mci_zx_execute_tuning,
.prepare_hs400_tuning   = dw_mci_zx_prepare_hs400_tuning,
.parse_dt   = dw_mci_zx_parse_dt,
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -2788,8 +2788,15 @@ static int dw_mci_init_slot_caps(struct
} 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;
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -542,6 +542,7 @@ struct dw_mci_slot {
 /**
  * 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.
  * @set_ios: handle bus specific extensions.
  * @parse_dt: parse implementation specific device tree properties.
@@ -553,6 +554,7 @@ struct dw_mci_slot {
  */
 struct dw_mci_drv_data {
unsigned long   *caps;
+   u32 num_caps;
int (*init)(struct dw_mci *host);
void(*set_ios)(struct dw_mci *host, struct mmc_ios *ios);
int (*parse_dt)(struct dw_mci *host);




[PATCH 4.14 019/110] mmc: dw_mmc: Fix out-of-bounds access for slots caps

2018-03-07 Thread Greg Kroah-Hartman
4.14-stable review patch.  If anyone has any objections, please let me know.

--

From: Shawn Lin 

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 
Signed-off-by: Shawn Lin 
Fixes: 800d78bfccb3 ("mmc: dw_mmc: add support for implementation specific 
callbacks")
Cc: 
Signed-off-by: Ulf Hansson 
Signed-off-by: Greg Kroah-Hartman 

---
 drivers/mmc/host/dw_mmc-exynos.c   |1 +
 drivers/mmc/host/dw_mmc-k3.c   |1 +
 drivers/mmc/host/dw_mmc-rockchip.c |1 +
 drivers/mmc/host/dw_mmc-zx.c   |1 +
 drivers/mmc/host/dw_mmc.c  |9 -
 drivers/mmc/host/dw_mmc.h  |2 ++
 6 files changed, 14 insertions(+), 1 deletion(-)

--- a/drivers/mmc/host/dw_mmc-exynos.c
+++ b/drivers/mmc/host/dw_mmc-exynos.c
@@ -487,6 +487,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,
.set_ios= dw_mci_exynos_set_ios,
.parse_dt   = dw_mci_exynos_parse_dt,
--- a/drivers/mmc/host/dw_mmc-k3.c
+++ b/drivers/mmc/host/dw_mmc-k3.c
@@ -210,6 +210,7 @@ static int dw_mci_hi6220_execute_tuning(
 
 static const struct dw_mci_drv_data hi6220_data = {
.caps   = dw_mci_hi6220_caps,
+   .num_caps   = ARRAY_SIZE(dw_mci_hi6220_caps),
.switch_voltage = dw_mci_hi6220_switch_voltage,
.set_ios= dw_mci_hi6220_set_ios,
.parse_dt   = dw_mci_hi6220_parse_dt,
--- a/drivers/mmc/host/dw_mmc-rockchip.c
+++ b/drivers/mmc/host/dw_mmc-rockchip.c
@@ -319,6 +319,7 @@ static const struct dw_mci_drv_data rk29
 
 static const struct dw_mci_drv_data rk3288_drv_data = {
.caps   = dw_mci_rk3288_dwmmc_caps,
+   .num_caps   = ARRAY_SIZE(dw_mci_rk3288_dwmmc_caps),
.set_ios= dw_mci_rk3288_set_ios,
.execute_tuning = dw_mci_rk3288_execute_tuning,
.parse_dt   = dw_mci_rk3288_parse_dt,
--- a/drivers/mmc/host/dw_mmc-zx.c
+++ b/drivers/mmc/host/dw_mmc-zx.c
@@ -195,6 +195,7 @@ static unsigned long zx_dwmmc_caps[3] =
 
 static const struct dw_mci_drv_data zx_drv_data = {
.caps   = zx_dwmmc_caps,
+   .num_caps   = ARRAY_SIZE(zx_dwmmc_caps),
.execute_tuning = dw_mci_zx_execute_tuning,
.prepare_hs400_tuning   = dw_mci_zx_prepare_hs400_tuning,
.parse_dt   = dw_mci_zx_parse_dt,
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -2788,8 +2788,15 @@ static int dw_mci_init_slot_caps(struct
} 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;
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -542,6 +542,7 @@ struct dw_mci_slot {
 /**
  * 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.
  * @set_ios: handle bus specific extensions.
  * @parse_dt: parse implementation specific device tree properties.
@@ -553,6 +554,7 @@ struct dw_mci_slot {
  */
 struct dw_mci_drv_data {
unsigned long   *caps;
+   u32 num_caps;
int (*init)(struct dw_mci *host);
void(*set_ios)(struct dw_mci *host, struct mmc_ios *ios);
int (*parse_dt)(struct dw_mci *host);