lkml.org 
[lkml]   [2020]   [Sep]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 5.8 26/29] spi: Fix memory leak on splited transfers
    Date
    From: Gustav Wiklander <gustavwi@axis.com>

    [ Upstream commit b59a7ca15464c78ea1ba3b280cfc5ac5ece11ade ]

    In the prepare_message callback the bus driver has the
    opportunity to split a transfer into smaller chunks.
    spi_map_msg is done after prepare_message.

    Function spi_res_release releases the splited transfers
    in the message. Therefore spi_res_release should be called
    after spi_map_msg.

    The previous try at this was commit c9ba7a16d0f1
    which released the splited transfers after
    spi_finalize_current_message had been called.
    This introduced a race since the message struct could be
    out of scope because the spi_sync call got completed.

    Fixes this leak on spi bus driver spi-bcm2835.c when transfer
    size is greater than 65532:

    Kmemleak:
    sg_alloc_table+0x28/0xc8
    spi_map_buf+0xa4/0x300
    __spi_pump_messages+0x370/0x748
    __spi_sync+0x1d4/0x270
    spi_sync+0x34/0x58
    spi_test_execute_msg+0x60/0x340 [spi_loopback_test]
    spi_test_run_iter+0x548/0x578 [spi_loopback_test]
    spi_test_run_test+0x94/0x140 [spi_loopback_test]
    spi_test_run_tests+0x150/0x180 [spi_loopback_test]
    spi_loopback_test_probe+0x50/0xd0 [spi_loopback_test]
    spi_drv_probe+0x84/0xe0

    Signed-off-by: Gustav Wiklander <gustavwi@axis.com>
    Link: https://lore.kernel.org/r/20200908151129.15915-1-gustav.wiklander@axis.com
    Signed-off-by: Mark Brown <broonie@kernel.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/spi/spi.c | 9 +++++++--
    1 file changed, 7 insertions(+), 2 deletions(-)

    diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
    index 5c5a95792c0d3..65ca552654794 100644
    --- a/drivers/spi/spi.c
    +++ b/drivers/spi/spi.c
    @@ -1305,8 +1305,6 @@ static int spi_transfer_one_message(struct spi_controller *ctlr,
    if (msg->status && ctlr->handle_err)
    ctlr->handle_err(ctlr, msg);

    - spi_res_release(ctlr, msg);
    -
    spi_finalize_current_message(ctlr);

    return ret;
    @@ -1694,6 +1692,13 @@ void spi_finalize_current_message(struct spi_controller *ctlr)

    spi_unmap_msg(ctlr, mesg);

    + /* In the prepare_messages callback the spi bus has the opportunity to
    + * split a transfer to smaller chunks.
    + * Release splited transfers here since spi_map_msg is done on the
    + * splited transfers.
    + */
    + spi_res_release(ctlr, mesg);
    +
    if (ctlr->cur_msg_prepared && ctlr->unprepare_message) {
    ret = ctlr->unprepare_message(ctlr, mesg);
    if (ret) {
    --
    2.25.1
    \
     
     \ /
      Last update: 2020-09-14 19:05    [W:4.657 / U:0.156 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site