All of lore.kernel.org
 help / color / mirror / Atom feed
From: James Hogan <james.hogan@imgtec.com>
To: Chris Ball <cjb@laptop.org>
Cc: Will Newton <will.newton@gmail.com>,
	Jaehoon Chung <jh80.chung@samsung.com>,
	Thomas Abraham <thomas.abraham@linaro.org>,
	Seungwon Jeon <tgih.jun@samsung.com>,
	linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] dw_mmc: fix multiple drv_data NULL dereferences
Date: Mon, 29 Oct 2012 09:34:46 +0000	[thread overview]
Message-ID: <508E4DB6.20504@imgtec.com> (raw)
In-Reply-To: <CAFbHwiSUoP_W=CK1hF+CYjxrJ1P6BR9=y_grEogmo5br6R_zuw@mail.gmail.com>

On 17/10/12 10:11, Will Newton wrote:
> Looks good to me too.
> 
> Acked-by: Will Newton <will.newton@imgtec.com>
> 
> On Wed, Oct 17, 2012 at 3:06 AM, Jaehoon Chung <jh80.chung@samsung.com> wrote:
>> Looks good to me.
>>
>> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>

Thanks for the acks Thomas, Seungwon, Jaehoon and Will.

Chris: Any chance of queueing this patch for v3.7?

Thanks
James

>>
>> On 10/16/2012 05:43 PM, James Hogan wrote:
>>> Commit 800d78bfccb3d38116abfda2a5b9c8afdbd5ea21 ("mmc: dw_mmc: add
>>> support for implementation specific callbacks") merged in v3.7-rc1.
>>>
>>> The above commit introduced multiple NULL pointer dereferences when
>>> the default dw_mci_pltfm_probe() is used, as it sets host->drv_data to
>>> NULL, and that's only checked against NULL in 1 out of the 7 cases where
>>> it is dereferenced.
>>>
>>> Signed-off-by: James Hogan <james.hogan@imgtec.com>
>>> ---
>>>  drivers/mmc/host/dw_mmc-pltfm.c |    4 ++--
>>>  drivers/mmc/host/dw_mmc.c       |   29 +++++++++++++++++------------
>>>  2 files changed, 19 insertions(+), 14 deletions(-)
>>>
>>> diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c
>>> index c960ca7..e595721 100644
>>> --- a/drivers/mmc/host/dw_mmc-pltfm.c
>>> +++ b/drivers/mmc/host/dw_mmc-pltfm.c
>>> @@ -50,8 +50,8 @@ int dw_mci_pltfm_register(struct platform_device *pdev,
>>>       if (!host->regs)
>>>               return -ENOMEM;
>>>
>>> -     if (host->drv_data->init) {
>>> -             ret = host->drv_data->init(host);
>>> +     if (drv_data && drv_data->init) {
>>> +             ret = drv_data->init(host);
>>>               if (ret)
>>>                       return ret;
>>>       }
>>> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
>>> index c2828f3..0dc6e33 100644
>>> --- a/drivers/mmc/host/dw_mmc.c
>>> +++ b/drivers/mmc/host/dw_mmc.c
>>> @@ -232,6 +232,7 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
>>>  {
>>>       struct mmc_data *data;
>>>       struct dw_mci_slot *slot = mmc_priv(mmc);
>>> +     struct dw_mci_drv_data *drv_data = slot->host->drv_data;
>>>       u32 cmdr;
>>>       cmd->error = -EINPROGRESS;
>>>
>>> @@ -261,8 +262,8 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
>>>                       cmdr |= SDMMC_CMD_DAT_WR;
>>>       }
>>>
>>> -     if (slot->host->drv_data->prepare_command)
>>> -             slot->host->drv_data->prepare_command(slot->host, &cmdr);
>>> +     if (drv_data && drv_data->prepare_command)
>>> +             drv_data->prepare_command(slot->host, &cmdr);
>>>
>>>       return cmdr;
>>>  }
>>> @@ -772,6 +773,7 @@ static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
>>>  static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>>>  {
>>>       struct dw_mci_slot *slot = mmc_priv(mmc);
>>> +     struct dw_mci_drv_data *drv_data = slot->host->drv_data;
>>>       u32 regs;
>>>
>>>       /* set default 1 bit mode */
>>> @@ -807,8 +809,8 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>>>               slot->clock = ios->clock;
>>>       }
>>>
>>> -     if (slot->host->drv_data->set_ios)
>>> -             slot->host->drv_data->set_ios(slot->host, ios);
>>> +     if (drv_data && drv_data->set_ios)
>>> +             drv_data->set_ios(slot->host, ios);
>>>
>>>       switch (ios->power_mode) {
>>>       case MMC_POWER_UP:
>>> @@ -1815,6 +1817,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
>>>  {
>>>       struct mmc_host *mmc;
>>>       struct dw_mci_slot *slot;
>>> +     struct dw_mci_drv_data *drv_data = host->drv_data;
>>>       int ctrl_id, ret;
>>>       u8 bus_width;
>>>
>>> @@ -1854,8 +1857,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
>>>       } else {
>>>               ctrl_id = to_platform_device(host->dev)->id;
>>>       }
>>> -     if (host->drv_data && host->drv_data->caps)
>>> -             mmc->caps |= host->drv_data->caps[ctrl_id];
>>> +     if (drv_data && drv_data->caps)
>>> +             mmc->caps |= drv_data->caps[ctrl_id];
>>>
>>>       if (host->pdata->caps2)
>>>               mmc->caps2 = host->pdata->caps2;
>>> @@ -1867,10 +1870,10 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
>>>       else
>>>               bus_width = 1;
>>>
>>> -     if (host->drv_data->setup_bus) {
>>> +     if (drv_data && drv_data->setup_bus) {
>>>               struct device_node *slot_np;
>>>               slot_np = dw_mci_of_find_slot_node(host->dev, slot->id);
>>> -             ret = host->drv_data->setup_bus(host, slot_np, bus_width);
>>> +             ret = drv_data->setup_bus(host, slot_np, bus_width);
>>>               if (ret)
>>>                       goto err_setup_bus;
>>>       }
>>> @@ -2035,6 +2038,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
>>>       struct dw_mci_board *pdata;
>>>       struct device *dev = host->dev;
>>>       struct device_node *np = dev->of_node;
>>> +     struct dw_mci_drv_data *drv_data = host->drv_data;
>>>       int idx, ret;
>>>
>>>       pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
>>> @@ -2062,8 +2066,8 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
>>>
>>>       of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms);
>>>
>>> -     if (host->drv_data->parse_dt) {
>>> -             ret = host->drv_data->parse_dt(host);
>>> +     if (drv_data && drv_data->parse_dt) {
>>> +             ret = drv_data->parse_dt(host);
>>>               if (ret)
>>>                       return ERR_PTR(ret);
>>>       }
>>> @@ -2080,6 +2084,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
>>>
>>>  int dw_mci_probe(struct dw_mci *host)
>>>  {
>>> +     struct dw_mci_drv_data *drv_data = host->drv_data;
>>>       int width, i, ret = 0;
>>>       u32 fifo_size;
>>>       int init_slots = 0;
>>> @@ -2127,8 +2132,8 @@ int dw_mci_probe(struct dw_mci *host)
>>>       else
>>>               host->bus_hz = clk_get_rate(host->ciu_clk);
>>>
>>> -     if (host->drv_data->setup_clock) {
>>> -             ret = host->drv_data->setup_clock(host);
>>> +     if (drv_data && drv_data->setup_clock) {
>>> +             ret = drv_data->setup_clock(host);
>>>               if (ret) {
>>>                       dev_err(host->dev,
>>>                               "implementation specific clock setup failed\n");
>>>
>>
>> --
>> 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


WARNING: multiple messages have this Message-ID (diff)
From: James Hogan <james.hogan@imgtec.com>
To: Chris Ball <cjb@laptop.org>
Cc: Will Newton <will.newton@gmail.com>,
	Jaehoon Chung <jh80.chung@samsung.com>,
	Thomas Abraham <thomas.abraham@linaro.org>,
	Seungwon Jeon <tgih.jun@samsung.com>, <linux-mmc@vger.kernel.org>,
	<linux-kernel@vger.kernel.org>
Subject: Re: [PATCH] dw_mmc: fix multiple drv_data NULL dereferences
Date: Mon, 29 Oct 2012 09:34:46 +0000	[thread overview]
Message-ID: <508E4DB6.20504@imgtec.com> (raw)
In-Reply-To: <CAFbHwiSUoP_W=CK1hF+CYjxrJ1P6BR9=y_grEogmo5br6R_zuw@mail.gmail.com>

On 17/10/12 10:11, Will Newton wrote:
> Looks good to me too.
> 
> Acked-by: Will Newton <will.newton@imgtec.com>
> 
> On Wed, Oct 17, 2012 at 3:06 AM, Jaehoon Chung <jh80.chung@samsung.com> wrote:
>> Looks good to me.
>>
>> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>

Thanks for the acks Thomas, Seungwon, Jaehoon and Will.

Chris: Any chance of queueing this patch for v3.7?

Thanks
James

>>
>> On 10/16/2012 05:43 PM, James Hogan wrote:
>>> Commit 800d78bfccb3d38116abfda2a5b9c8afdbd5ea21 ("mmc: dw_mmc: add
>>> support for implementation specific callbacks") merged in v3.7-rc1.
>>>
>>> The above commit introduced multiple NULL pointer dereferences when
>>> the default dw_mci_pltfm_probe() is used, as it sets host->drv_data to
>>> NULL, and that's only checked against NULL in 1 out of the 7 cases where
>>> it is dereferenced.
>>>
>>> Signed-off-by: James Hogan <james.hogan@imgtec.com>
>>> ---
>>>  drivers/mmc/host/dw_mmc-pltfm.c |    4 ++--
>>>  drivers/mmc/host/dw_mmc.c       |   29 +++++++++++++++++------------
>>>  2 files changed, 19 insertions(+), 14 deletions(-)
>>>
>>> diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c
>>> index c960ca7..e595721 100644
>>> --- a/drivers/mmc/host/dw_mmc-pltfm.c
>>> +++ b/drivers/mmc/host/dw_mmc-pltfm.c
>>> @@ -50,8 +50,8 @@ int dw_mci_pltfm_register(struct platform_device *pdev,
>>>       if (!host->regs)
>>>               return -ENOMEM;
>>>
>>> -     if (host->drv_data->init) {
>>> -             ret = host->drv_data->init(host);
>>> +     if (drv_data && drv_data->init) {
>>> +             ret = drv_data->init(host);
>>>               if (ret)
>>>                       return ret;
>>>       }
>>> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
>>> index c2828f3..0dc6e33 100644
>>> --- a/drivers/mmc/host/dw_mmc.c
>>> +++ b/drivers/mmc/host/dw_mmc.c
>>> @@ -232,6 +232,7 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
>>>  {
>>>       struct mmc_data *data;
>>>       struct dw_mci_slot *slot = mmc_priv(mmc);
>>> +     struct dw_mci_drv_data *drv_data = slot->host->drv_data;
>>>       u32 cmdr;
>>>       cmd->error = -EINPROGRESS;
>>>
>>> @@ -261,8 +262,8 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
>>>                       cmdr |= SDMMC_CMD_DAT_WR;
>>>       }
>>>
>>> -     if (slot->host->drv_data->prepare_command)
>>> -             slot->host->drv_data->prepare_command(slot->host, &cmdr);
>>> +     if (drv_data && drv_data->prepare_command)
>>> +             drv_data->prepare_command(slot->host, &cmdr);
>>>
>>>       return cmdr;
>>>  }
>>> @@ -772,6 +773,7 @@ static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
>>>  static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>>>  {
>>>       struct dw_mci_slot *slot = mmc_priv(mmc);
>>> +     struct dw_mci_drv_data *drv_data = slot->host->drv_data;
>>>       u32 regs;
>>>
>>>       /* set default 1 bit mode */
>>> @@ -807,8 +809,8 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>>>               slot->clock = ios->clock;
>>>       }
>>>
>>> -     if (slot->host->drv_data->set_ios)
>>> -             slot->host->drv_data->set_ios(slot->host, ios);
>>> +     if (drv_data && drv_data->set_ios)
>>> +             drv_data->set_ios(slot->host, ios);
>>>
>>>       switch (ios->power_mode) {
>>>       case MMC_POWER_UP:
>>> @@ -1815,6 +1817,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
>>>  {
>>>       struct mmc_host *mmc;
>>>       struct dw_mci_slot *slot;
>>> +     struct dw_mci_drv_data *drv_data = host->drv_data;
>>>       int ctrl_id, ret;
>>>       u8 bus_width;
>>>
>>> @@ -1854,8 +1857,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
>>>       } else {
>>>               ctrl_id = to_platform_device(host->dev)->id;
>>>       }
>>> -     if (host->drv_data && host->drv_data->caps)
>>> -             mmc->caps |= host->drv_data->caps[ctrl_id];
>>> +     if (drv_data && drv_data->caps)
>>> +             mmc->caps |= drv_data->caps[ctrl_id];
>>>
>>>       if (host->pdata->caps2)
>>>               mmc->caps2 = host->pdata->caps2;
>>> @@ -1867,10 +1870,10 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
>>>       else
>>>               bus_width = 1;
>>>
>>> -     if (host->drv_data->setup_bus) {
>>> +     if (drv_data && drv_data->setup_bus) {
>>>               struct device_node *slot_np;
>>>               slot_np = dw_mci_of_find_slot_node(host->dev, slot->id);
>>> -             ret = host->drv_data->setup_bus(host, slot_np, bus_width);
>>> +             ret = drv_data->setup_bus(host, slot_np, bus_width);
>>>               if (ret)
>>>                       goto err_setup_bus;
>>>       }
>>> @@ -2035,6 +2038,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
>>>       struct dw_mci_board *pdata;
>>>       struct device *dev = host->dev;
>>>       struct device_node *np = dev->of_node;
>>> +     struct dw_mci_drv_data *drv_data = host->drv_data;
>>>       int idx, ret;
>>>
>>>       pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
>>> @@ -2062,8 +2066,8 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
>>>
>>>       of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms);
>>>
>>> -     if (host->drv_data->parse_dt) {
>>> -             ret = host->drv_data->parse_dt(host);
>>> +     if (drv_data && drv_data->parse_dt) {
>>> +             ret = drv_data->parse_dt(host);
>>>               if (ret)
>>>                       return ERR_PTR(ret);
>>>       }
>>> @@ -2080,6 +2084,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
>>>
>>>  int dw_mci_probe(struct dw_mci *host)
>>>  {
>>> +     struct dw_mci_drv_data *drv_data = host->drv_data;
>>>       int width, i, ret = 0;
>>>       u32 fifo_size;
>>>       int init_slots = 0;
>>> @@ -2127,8 +2132,8 @@ int dw_mci_probe(struct dw_mci *host)
>>>       else
>>>               host->bus_hz = clk_get_rate(host->ciu_clk);
>>>
>>> -     if (host->drv_data->setup_clock) {
>>> -             ret = host->drv_data->setup_clock(host);
>>> +     if (drv_data && drv_data->setup_clock) {
>>> +             ret = drv_data->setup_clock(host);
>>>               if (ret) {
>>>                       dev_err(host->dev,
>>>                               "implementation specific clock setup failed\n");
>>>
>>
>> --
>> 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


  reply	other threads:[~2012-10-29  9:34 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-10-16  8:43 [PATCH] dw_mmc: fix multiple drv_data NULL dereferences James Hogan
2012-10-16  8:43 ` James Hogan
2012-10-16 10:49 ` Thomas Abraham
2012-10-16 10:54 ` Seungwon Jeon
2012-10-17  2:06 ` Jaehoon Chung
2012-10-17  9:11   ` Will Newton
2012-10-29  9:34     ` James Hogan [this message]
2012-10-29  9:34       ` James Hogan
2012-10-29 13:39       ` Chris Ball
2012-10-29 13:39         ` Chris Ball
2012-11-08 14:26         ` [PATCH] dw_mmc: fix more const pointer warnings Arnd Bergmann
2012-11-08 14:35           ` Chris Ball
2012-11-09  5:44             ` Jaehoon Chung

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=508E4DB6.20504@imgtec.com \
    --to=james.hogan@imgtec.com \
    --cc=cjb@laptop.org \
    --cc=jh80.chung@samsung.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mmc@vger.kernel.org \
    --cc=tgih.jun@samsung.com \
    --cc=thomas.abraham@linaro.org \
    --cc=will.newton@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.