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 <anandakumarm@nvidia.com>
Reviewed-on: http://git-master/r/1118936
(cherry picked from commit 9f7120e03e66b5f6e2bf67f09063da20945be238)
Reviewed-on: http://git-master/r/1458894
Signed-off-by: Nitin Kumbhar <nkumbhar@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1537317
Reviewed-by: svccoveritychecker <svccoveritychecker@nvidia.com>
GVS: Gerrit_Virtual_Submit
This commit is contained in:
Ajay Nandakumar
2016-04-01 15:45:18 +05:30
committed by Laxman Dewangan
parent a37d2fe7e3
commit 34470e65b4
3 changed files with 34 additions and 5 deletions

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}
}
}