lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date:	Mon, 27 Oct 2014 13:12:04 +0100
From:	Ulf Hansson <ulf.hansson@...aro.org>
To:	Matteo Facchinetti <matteo.facchinetti@...ius-es.it>
Cc:	Chris Ball <chris@...ntf.net>, Alexander Shiyan <shc_work@...l.ru>,
	Sascha Hauer <s.hauer@...gutronix.de>,
	Peter Griffin <peter.griffin@...aro.org>,
	linux-mmc <linux-mmc@...r.kernel.org>,
	"linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
	linucppc-dev@...ts.ozlabs.org, Anatolij Gustschin <agust@...x.de>,
	gsi@...x.de, sbabic@...x.de
Subject: Re: [PATCH 1/2] mmc: mxcmmc: fix race condition when dma finish a
 data transfer

On 30 September 2014 16:59, Matteo Facchinetti
<matteo.facchinetti@...ius-es.it> wrote:
> From: Matteo Facchinetti <matteo.facchinetti@...ius-es.it>
>
> During a read of data block using dma, driver might have two ways to finish to read
> and free the resources:
> 1) checking STATUS_DATA_TRANS_DONE mask, in the mxcmci_irq() routine
>    (pending to mmc irq)
> 2) mxmmc driver, registers also a mxcmci_dma_callback() and when transfer is finished,
>    dma driver calls this callback. (pending to dma irq)
> Both ways are concurrent with each other.
>
> Race condition happens when following events occur:
> /* (1) mxcmci driver start data transfer */
>          158.418970: mpc_dma_execute: mpc_dma_execute(): will_access_peripheral start cid=31
>          158.418976: mpc_dma_issue_pending <-mxcmci_request
>          158.418983: mxcmci_start_cmd <-mxcmci_request
> /* (2) mxcmci driver receive mmc irq */
>          158.419656: mxcmci_irq <-handle_irq_event_percpu
>          158.419692: mxcmci_read_response <-mxcmci_irq
> /* (3) mxcmci driver checks that transfer is complete and call mxcmci_finish_data() */
>          158.419726: mxcmci_data_done <-mxcmci_irq
>          158.419729: mxcmci_finish_data <-mxcmci_data_done
>          158.419733: dma_direct_unmap_sg <-mxcmci_finish_data
>          158.419736: mxcmci_swap_buffers.isra.24 <-mxcmci_finish_data
>          158.419762: mxcmci_read_response <-mxcmci_data_done
> /* (4) mxcmci driver (no dma): send stop command */
>          158.419765: mxcmci_start_cmd <-mxcmci_data_done
> /* (5) mxcmci driver (no dma): receive the stop command irq response */
>          158.419782: mxcmci_irq <-handle_irq_event_percpu
>          158.419812: mxcmci_read_response <-mxcmci_irq
>          158.419843: mxcmci_finish_request <-mxcmci_irq
> /* (6) dma driver: receive dma irq (finish data transfer) related by request on step 1 */
>          158.419853: mpc_dma_irq <-handle_irq_event_percpu
>          158.420001: mpc_dma_irq_process <-mpc_dma_irq
>          158.420004: mpc_dma_irq_process <-mpc_dma_irq
> /* (7) dma driver: start dma tasklet to finish the dma irq handling */
>          158.420008: mpc_dma_irq_process: mpc_dma_irq_process(): completed ch:31
> /* (8) mxcmci driver: start next data transfer using dma */
>          158.420174: mxcmci_request <-mmc_start_req
>          158.420182: dma_direct_map_sg <-mxcmci_request
>          158.420192: mpc_dma_prep_slave_sg <-mxcmci_request
> /* (9) dma driver: schedule irq tasklet and execute mxcmci dma driver callback */
>          158.420250: mpc_dma_tasklet <-tasklet_action
>          158.420254: mpc_dma_process_completed <-tasklet_action
>          158.420267: mxcmci_dma_callback <-mpc_dma_process_completed
> /* ERROR!!! (10) mxcmci driver callback works on dma data related to the step 1
>                  that is already finished */
>          158.420271: mxcmci_data_done <-mpc_dma_process_completed
>          158.420273: mxcmci_finish_data <-mxcmci_data_done
> /* ERROR!!! (11) mxcmci driver: clear data that should be used by step 8 and
>                  send an other mmc stop command (already sended on step 4) */
>          158.420276: dma_direct_unmap_sg <-mxcmci_finish_data
>          158.420279: mxcmci_swap_buffers.isra.24 <-mxcmci_finish_data
>          158.420330: mxcmci_read_response <-mxcmci_data_done
>          158.420333: mxcmci_start_cmd <-mxcmci_data_done
>          158.420338: dma_run_dependencies <-mpc_dma_process_completed
> ...
> ...
> ...
>          168.474223: mxcmci_watchdog <-call_timer_fn
>          168.474236: mxcmci_watchdog: mxcmci_watchdog
>          168.474397: mpc_dma_device_control <-mxcmci_watchdog
>
>
> In accordance with the other drivers that using the dma engine,
> fix it, leaving *only* to dma driver the complete control to
> ending the read operation.
>
> Removing STATUS_READ_OP_DONE event activation, has as effect
> to force mxcmci driver to handle the finish data transfer only
> by mxcmci dma callback.
>
> Signed-off-by: Matteo Facchinetti <matteo.facchinetti@...ius-es.it>

Thanks! Applied for next!

Kind regards
Uffe

> ---
>  drivers/mmc/host/mxcmmc.c | 13 +++----------
>  1 file changed, 3 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
> index ad11142..536a898 100644
> --- a/drivers/mmc/host/mxcmmc.c
> +++ b/drivers/mmc/host/mxcmmc.c
> @@ -373,13 +373,9 @@ static void mxcmci_dma_callback(void *data)
>         del_timer(&host->watchdog);
>
>         stat = mxcmci_readl(host, MMC_REG_STATUS);
> -       mxcmci_writel(host, stat & ~STATUS_DATA_TRANS_DONE, MMC_REG_STATUS);
>
>         dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat);
>
> -       if (stat & STATUS_READ_OP_DONE)
> -               mxcmci_writel(host, STATUS_READ_OP_DONE, MMC_REG_STATUS);
> -
>         mxcmci_data_done(host, stat);
>  }
>
> @@ -743,10 +739,8 @@ static irqreturn_t mxcmci_irq(int irq, void *devid)
>         sdio_irq = (stat & STATUS_SDIO_INT_ACTIVE) && host->use_sdio;
>         spin_unlock_irqrestore(&host->lock, flags);
>
> -       if (mxcmci_use_dma(host) &&
> -           (stat & (STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE)))
> -               mxcmci_writel(host, STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE,
> -                       MMC_REG_STATUS);
> +       if (mxcmci_use_dma(host) && (stat & (STATUS_WRITE_OP_DONE)))
> +               mxcmci_writel(host, STATUS_WRITE_OP_DONE, MMC_REG_STATUS);
>
>         if (sdio_irq) {
>                 mxcmci_writel(host, STATUS_SDIO_INT_ACTIVE, MMC_REG_STATUS);
> @@ -756,8 +750,7 @@ static irqreturn_t mxcmci_irq(int irq, void *devid)
>         if (stat & STATUS_END_CMD_RESP)
>                 mxcmci_cmd_done(host, stat);
>
> -       if (mxcmci_use_dma(host) &&
> -                 (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE))) {
> +       if (mxcmci_use_dma(host) && (stat & STATUS_WRITE_OP_DONE)) {
>                 del_timer(&host->watchdog);
>                 mxcmci_data_done(host, stat);
>         }
> --
> 1.8.3.2
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ