diff mbox

[2/2] mmc: dw_mmc: Fix out-of-bounds access for slot's caps

Message ID 1519453043-31820-2-git-send-email-shawn.lin@rock-chips.com (mailing list archive)
State New, archived
Headers show

Commit Message

Shawn Lin Feb. 24, 2018, 6:17 a.m. UTC
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>
---

 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(-)

Comments

Ulf Hansson Feb. 27, 2018, 11:27 a.m. UTC | #1
On 24 February 2018 at 07:17, Shawn Lin <shawn.lin@rock-chips.com> wrote:
> 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>

Thanks, applied for fixes!

Should we add a stable tag as well?

Kind regards
Uffe

> ---
>
>  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(-)
>
> diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c
> index 3502679..fa41d94 100644
> --- a/drivers/mmc/host/dw_mmc-exynos.c
> +++ b/drivers/mmc/host/dw_mmc-exynos.c
> @@ -487,6 +487,7 @@ static int dw_mci_exynos_prepare_hs400_tuning(struct dw_mci *host,
>
>  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,
> diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
> index 73fd75c..eb53e37 100644
> --- a/drivers/mmc/host/dw_mmc-k3.c
> +++ b/drivers/mmc/host/dw_mmc-k3.c
> @@ -207,6 +207,7 @@ static int dw_mci_hi6220_execute_tuning(struct dw_mci_slot *slot, u32 opcode)
>
>  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,
> diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c
> index a3f1c2b..3392952 100644
> --- a/drivers/mmc/host/dw_mmc-rockchip.c
> +++ b/drivers/mmc/host/dw_mmc-rockchip.c
> @@ -319,6 +319,7 @@ static int dw_mci_rockchip_init(struct dw_mci *host)
>
>  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,
> diff --git a/drivers/mmc/host/dw_mmc-zx.c b/drivers/mmc/host/dw_mmc-zx.c
> index d38e94a..c06b539 100644
> --- a/drivers/mmc/host/dw_mmc-zx.c
> +++ b/drivers/mmc/host/dw_mmc-zx.c
> @@ -195,6 +195,7 @@ static int dw_mci_zx_parse_dt(struct dw_mci *host)
>
>  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,
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> index d9128a5..aecc3e2 100644
> --- a/drivers/mmc/host/dw_mmc.c
> +++ b/drivers/mmc/host/dw_mmc.c
> @@ -2783,8 +2783,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;
> diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
> index e3124f0..1424bd4 100644
> --- a/drivers/mmc/host/dw_mmc.h
> +++ b/drivers/mmc/host/dw_mmc.h
> @@ -543,6 +543,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.
> @@ -554,6 +555,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);
> --
> 1.9.1
>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Shawn Lin Feb. 27, 2018, 1:42 p.m. UTC | #2
On 2018/2/27 19:27, Ulf Hansson wrote:
> On 24 February 2018 at 07:17, Shawn Lin <shawn.lin@rock-chips.com> wrote:
>> 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>
> 
> Thanks, applied for fixes!
> 
> Should we add a stable tag as well?
> 

I noticed patch[1] was intended to be backported as far
as possible, but I suspected how far it could be for dw_mmc, since
the code changed a lot after introducing this piece of code:).
Anyway, it still may be worth to have a try, so

Fixes: 800d78bfccb3 ("mmc: dw_mmc: add support for implementation 
specific callbacks")
Cc: <stable@vger.kernel.org>


[1] https://patchwork.kernel.org/patch/10230673/

> Kind regards
> Uffe
> 
>> ---
>>
>>   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(-)
>>
>> diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c
>> index 3502679..fa41d94 100644
>> --- a/drivers/mmc/host/dw_mmc-exynos.c
>> +++ b/drivers/mmc/host/dw_mmc-exynos.c
>> @@ -487,6 +487,7 @@ static int dw_mci_exynos_prepare_hs400_tuning(struct dw_mci *host,
>>
>>   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,
>> diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
>> index 73fd75c..eb53e37 100644
>> --- a/drivers/mmc/host/dw_mmc-k3.c
>> +++ b/drivers/mmc/host/dw_mmc-k3.c
>> @@ -207,6 +207,7 @@ static int dw_mci_hi6220_execute_tuning(struct dw_mci_slot *slot, u32 opcode)
>>
>>   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,
>> diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c
>> index a3f1c2b..3392952 100644
>> --- a/drivers/mmc/host/dw_mmc-rockchip.c
>> +++ b/drivers/mmc/host/dw_mmc-rockchip.c
>> @@ -319,6 +319,7 @@ static int dw_mci_rockchip_init(struct dw_mci *host)
>>
>>   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,
>> diff --git a/drivers/mmc/host/dw_mmc-zx.c b/drivers/mmc/host/dw_mmc-zx.c
>> index d38e94a..c06b539 100644
>> --- a/drivers/mmc/host/dw_mmc-zx.c
>> +++ b/drivers/mmc/host/dw_mmc-zx.c
>> @@ -195,6 +195,7 @@ static int dw_mci_zx_parse_dt(struct dw_mci *host)
>>
>>   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,
>> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
>> index d9128a5..aecc3e2 100644
>> --- a/drivers/mmc/host/dw_mmc.c
>> +++ b/drivers/mmc/host/dw_mmc.c
>> @@ -2783,8 +2783,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;
>> diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
>> index e3124f0..1424bd4 100644
>> --- a/drivers/mmc/host/dw_mmc.h
>> +++ b/drivers/mmc/host/dw_mmc.h
>> @@ -543,6 +543,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.
>> @@ -554,6 +555,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);
>> --
>> 1.9.1
>>
>>
> 
> 
>
diff mbox

Patch

diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c
index 3502679..fa41d94 100644
--- a/drivers/mmc/host/dw_mmc-exynos.c
+++ b/drivers/mmc/host/dw_mmc-exynos.c
@@ -487,6 +487,7 @@  static int dw_mci_exynos_prepare_hs400_tuning(struct dw_mci *host,
 
 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,
diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
index 73fd75c..eb53e37 100644
--- a/drivers/mmc/host/dw_mmc-k3.c
+++ b/drivers/mmc/host/dw_mmc-k3.c
@@ -207,6 +207,7 @@  static int dw_mci_hi6220_execute_tuning(struct dw_mci_slot *slot, u32 opcode)
 
 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,
diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c
index a3f1c2b..3392952 100644
--- a/drivers/mmc/host/dw_mmc-rockchip.c
+++ b/drivers/mmc/host/dw_mmc-rockchip.c
@@ -319,6 +319,7 @@  static int dw_mci_rockchip_init(struct dw_mci *host)
 
 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,
diff --git a/drivers/mmc/host/dw_mmc-zx.c b/drivers/mmc/host/dw_mmc-zx.c
index d38e94a..c06b539 100644
--- a/drivers/mmc/host/dw_mmc-zx.c
+++ b/drivers/mmc/host/dw_mmc-zx.c
@@ -195,6 +195,7 @@  static int dw_mci_zx_parse_dt(struct dw_mci *host)
 
 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,
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index d9128a5..aecc3e2 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -2783,8 +2783,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;
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index e3124f0..1424bd4 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -543,6 +543,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.
@@ -554,6 +555,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);