From 34470e65b4cd80f35d84fad7d7dd9890182e26a4 Mon Sep 17 00:00:00 2001 From: Ajay Nandakumar Date: Fri, 1 Apr 2016 15:45:18 +0530 Subject: [PATCH] platform: nvadsp: check evp address before copying When ADSP OS is loaded from adsp.elf, it loads two sections : adsp os and the vector table. The vector table is copied to a local buffer before writing to the EVP registers. There is a probability that, if the adsp.elf is hacked / modified by an attacker, it can write to other APE register spaces. Hence, the destination address obtained from the elf is checked with evp base before copying. Also, this fixes out of array-bound writing to evp buffer. Bug 1684844 Change-Id: I8981dc5a5db8e0c0653ff46a1576df2c82e420be Signed-off-by: Ajay Nandakumar Reviewed-on: http://git-master/r/1118936 (cherry picked from commit 9f7120e03e66b5f6e2bf67f09063da20945be238) Reviewed-on: http://git-master/r/1458894 Signed-off-by: Nitin Kumbhar Reviewed-on: https://git-master.nvidia.com/r/1537317 Reviewed-by: svccoveritychecker GVS: Gerrit_Virtual_Submit --- drivers/platform/tegra/nvadsp/dev.c | 14 ++++++++++++++ drivers/platform/tegra/nvadsp/dev.h | 9 ++++++++- drivers/platform/tegra/nvadsp/os.c | 16 ++++++++++++---- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/drivers/platform/tegra/nvadsp/dev.c b/drivers/platform/tegra/nvadsp/dev.c index f1756870..5366e156 100644 --- a/drivers/platform/tegra/nvadsp/dev.c +++ b/drivers/platform/tegra/nvadsp/dev.c @@ -159,6 +159,15 @@ static int __init nvadsp_parse_dt(struct platform_device *pdev) } } + for (iter = 0; iter < ADSP_EVP_END; iter++) { + if (of_property_read_u32_index(dev->of_node, + "nvidia,adsp-evp-base", + iter, &drv_data->evp_base[iter])) { + dev_err(dev, "adsp memory dt %d not found\n", iter); + return -EINVAL; + } + } + drv_data->adsp_unit_fpga = of_property_read_bool(dev->of_node, "nvidia,adsp_unit_fpga"); @@ -178,6 +187,11 @@ static int __init nvadsp_parse_dt(struct platform_device *pdev) } nvadsp_parse_clk_entries(pdev); + drv_data->state.evp = devm_kzalloc(dev, + drv_data->evp_base[ADSP_EVP_SIZE], GFP_KERNEL); + if (!drv_data->state.evp) + return -ENOMEM; + return 0; } diff --git a/drivers/platform/tegra/nvadsp/dev.h b/drivers/platform/tegra/nvadsp/dev.h index df1c4073..adc96fa0 100644 --- a/drivers/platform/tegra/nvadsp/dev.h +++ b/drivers/platform/tegra/nvadsp/dev.h @@ -36,6 +36,12 @@ #include "amc.h" #include "os.h" +enum adsp_evp_dt { + ADSP_EVP_BASE, + ADSP_EVP_SIZE, + ADSP_EVP_END, +}; + enum adsp_unit_fpga_reset { ADSP_ASSERT, ADSP_DEASSERT, @@ -71,7 +77,7 @@ struct nvadsp_pm_state { u32 aram[AMC_ARAM_WSIZE]; uint32_t amc_regs[AMC_REGS]; uint32_t amisc_regs[AMISC_REGS]; - u32 evp[AMC_EVP_WSIZE]; + u32 *evp; void *evp_ptr; }; @@ -140,6 +146,7 @@ struct nvadsp_drv_data { int agic_irqs[NVADSP_VIRQ_MAX]; struct tegra_bwmgr_client *bwmgr; + u32 evp_base[ADSP_EVP_END]; }; #define ADSP_CONFIG 0x04 diff --git a/drivers/platform/tegra/nvadsp/os.c b/drivers/platform/tegra/nvadsp/os.c index 80534612..4c972196 100644 --- a/drivers/platform/tegra/nvadsp/os.c +++ b/drivers/platform/tegra/nvadsp/os.c @@ -559,12 +559,20 @@ static int nvadsp_os_elf_load(const struct firmware *fw) /* put the segment where the remote processor expects it */ if (filesz) { - if (!is_adsp_dram_addr(da)) { + if (is_adsp_dram_addr(da)) + memcpy(va, elf_data + offset, filesz); + else if ((da == drv_data->evp_base[ADSP_EVP_BASE]) && + (filesz == drv_data->evp_base[ADSP_EVP_SIZE])) { + drv_data->state.evp_ptr = va; memcpy(drv_data->state.evp, - elf_data + offset, filesz); - } else - memcpy(va, elf_data + offset, filesz); + elf_data + offset, filesz); + } else { + dev_err(dev, "can't load mem pa:0x%x va:%p\n", + da, va); + ret = -EINVAL; + break; + } } }