[PATCH] accel/amdxdna: check the command payload before using it
Taimuraz Kaitmazov <[email protected]>
| Newsgroups | org.freedesktop.lists.dri-devel |
|---|---|
| Message-ID | <[email protected]> |
amdxdna_cmd_get_payload() answers NULL when the command BO cannot be mapped, and on that path it returns before writing *size, so the caller's length keeps whatever the stack held. Its eight callers in aie2_message.c use both without checking either: cmd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len); if (cmd_len > sizeof(cu_req->payload)) return -EINVAL; ... memcpy(cu_req->payload, cmd, cmd_len); so an uninitialised length decides the bounds check and then a NULL source is copied from. The mapping fails under vmalloc pressure today, and any future reason for amdxdna_gem_vmap() to refuse widens it. Check the pointer, and clear the length before the early return so a caller that ignores the pointer still reads a defined value. Signed-off-by: Taimuraz Kaitmazov <[email protected]> --- drivers/accel/amdxdna/aie2_message.c | 16 ++++++++++++++++ drivers/accel/amdxdna/amdxdna_ctx.c | 3 +++ 2 files changed, 19 insertions(+) diff --git a/drivers/accel/amdxdna/aie2_message.c b/drivers/accel/amdxdna/aie2_message.c index dfe0fbdf066d..6f258206d508 100644 --- a/drivers/accel/amdxdna/aie2_message.c +++ b/drivers/accel/amdxdna/aie2_message.c @@ -555,6 +555,8 @@ static int aie2_init_exec_cu_req(struct amdxdna_gem_obj *cmd_bo, void *req, void *cmd; cmd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len); + if (!cmd) + return -EINVAL; if (cmd_len > sizeof(cu_req->payload)) return -EINVAL; @@ -577,6 +579,8 @@ static int aie2_init_exec_dpu_req(struct amdxdna_gem_obj *cmd_bo, void *req, u32 cmd_len; sn = amdxdna_cmd_get_payload(cmd_bo, &cmd_len); + if (!sn) + return -EINVAL; if (cmd_len - sizeof(*sn) > sizeof(dpu_req->payload)) return -EINVAL; @@ -622,6 +626,8 @@ aie2_cmdlist_fill_cf(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *size) void *cmd; cmd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len); + if (!cmd) + return -EINVAL; if (*size < sizeof(*cf_slot) + cmd_len) return -EINVAL; @@ -645,6 +651,8 @@ aie2_cmdlist_fill_dpu(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *size) u32 arg_sz; sn = amdxdna_cmd_get_payload(cmd_bo, &cmd_len); + if (!sn) + return -EINVAL; arg_sz = cmd_len - sizeof(*sn); if (cmd_len < sizeof(*sn) || arg_sz > MAX_DPU_ARGS_SIZE) return -EINVAL; @@ -705,6 +713,8 @@ aie2_cmdlist_fill_npu_cf(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *siz void *cmd; cmd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len); + if (!cmd) + return -EINVAL; if (*size < sizeof(*npu_slot) + cmd_len) return -EINVAL; @@ -730,6 +740,8 @@ aie2_cmdlist_fill_npu_dpu(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *si u32 arg_sz; sn = amdxdna_cmd_get_payload(cmd_bo, &cmd_len); + if (!sn) + return -EINVAL; arg_sz = cmd_len - sizeof(*sn); if (cmd_len < sizeof(*sn) || arg_sz > MAX_NPU_ARGS_SIZE) return -EINVAL; @@ -762,6 +774,8 @@ aie2_cmdlist_fill_npu_preempt(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t u32 arg_sz; pd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len); + if (!pd) + return -EINVAL; arg_sz = cmd_len - sizeof(*pd); if (cmd_len < sizeof(*pd) || arg_sz > MAX_NPU_ARGS_SIZE) return -EINVAL; @@ -798,6 +812,8 @@ aie2_cmdlist_fill_npu_elf(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *si u32 arg_sz; pd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len); + if (!pd) + return -EINVAL; arg_sz = cmd_len - sizeof(*pd); if (cmd_len < sizeof(*pd) || arg_sz > MAX_NPU_ARGS_SIZE) return -EINVAL; diff --git a/drivers/accel/amdxdna/amdxdna_ctx.c b/drivers/accel/amdxdna/amdxdna_ctx.c index 31a414c3f0d9..505c249e142e 100644 --- a/drivers/accel/amdxdna/amdxdna_ctx.c +++ b/drivers/accel/amdxdna/amdxdna_ctx.c @@ -117,6 +117,9 @@ void *amdxdna_cmd_get_payload(struct amdxdna_gem_obj *abo, u32 *size) struct amdxdna_cmd *cmd = amdxdna_gem_vmap(abo); u32 num_masks, count; + if (size) + *size = 0; + if (!cmd) return NULL; -- 2.55.0