From 1117ea1286d67e77325e1b5db289037aaacf03b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konsta=20H=C3=B6ltt=C3=A4?= Date: Fri, 21 Aug 2020 15:35:11 +0300 Subject: [PATCH] gpu: nvgpu: ce: check address ranges before exec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The source and destination addresses are masked to low 40 bits only. Make sure that the input params don't cross that; it would mean a bug somewhere in the caller side. Silently truncating values could cause unexpected behaviour, but no device even has that much memory. Also rename the src_buf and dst_buf to src_paddr and dst_paddr to emphasize that the addresses are gpu physical. Jira NVGPU-5172 Change-Id: I30653bf93791517991d04e4ba43220b5b541f581 Signed-off-by: Konsta Hölttä Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2402031 Reviewed-by: automaticguardword Reviewed-by: svc-mobile-coverity Reviewed-by: svc-mobile-misra Reviewed-by: Deepak Nibade Reviewed-by: Alex Waterman Reviewed-by: mobile promotions GVS: Gerrit_Virtual_Submit Tested-by: mobile promotions --- drivers/gpu/nvgpu/common/ce/ce_app.c | 36 +++++++++++++++--------- drivers/gpu/nvgpu/common/ce/ce_priv.h | 4 +-- drivers/gpu/nvgpu/include/nvgpu/ce_app.h | 7 +++-- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/nvgpu/common/ce/ce_app.c b/drivers/gpu/nvgpu/common/ce/ce_app.c index 3466ab12c..ecf1d0411 100644 --- a/drivers/gpu/nvgpu/common/ce/ce_app.c +++ b/drivers/gpu/nvgpu/common/ce/ce_app.c @@ -52,8 +52,8 @@ static inline u32 nvgpu_ce_get_valid_launch_flags(struct gk20a *g, int nvgpu_ce_execute_ops(struct gk20a *g, u32 ce_ctx_id, - u64 src_buf, - u64 dst_buf, + u64 src_paddr, + u64 dst_paddr, u64 size, u32 payload, u32 launch_flags, @@ -90,6 +90,16 @@ int nvgpu_ce_execute_ops(struct gk20a *g, goto end; } + if (src_paddr > NVGPU_CE_MAX_ADDRESS) { + ret = -EINVAL; + goto end; + } + + if (dst_paddr > NVGPU_CE_MAX_ADDRESS) { + ret = -EINVAL; + goto end; + } + nvgpu_mutex_acquire(&ce_app->app_mutex); nvgpu_list_for_each_entry_safe(ce_ctx, ce_ctx_save, @@ -140,8 +150,8 @@ int nvgpu_ce_execute_ops(struct gk20a *g, (u64)(cmd_buf_read_offset * sizeof(u32))); dma_copy_class = g->ops.get_litter_value(g, GPU_LIT_DMA_COPY_CLASS); - method_size = nvgpu_ce_prepare_submit(src_buf, - dst_buf, + method_size = nvgpu_ce_prepare_submit(src_paddr, + dst_paddr, size, &cmd_buf_cpu_va[cmd_buf_read_offset], payload, @@ -235,7 +245,7 @@ static void nvgpu_ce_delete_gpu_context_locked(struct nvgpu_ce_gpu_ctx *ce_ctx) } static u32 nvgpu_prepare_ce_op(u32 *cmd_buf_cpu_va, - u64 src_buf, u64 dst_buf, + u64 src_paddr, u64 dst_paddr, u32 width, u32 height, u32 payload, bool mode_transfer, u32 launch_flags) { @@ -245,9 +255,9 @@ static u32 nvgpu_prepare_ce_op(u32 *cmd_buf_cpu_va, if (mode_transfer) { /* setup the source */ cmd_buf_cpu_va[methodSize++] = 0x20028100; - cmd_buf_cpu_va[methodSize++] = (u64_hi32(src_buf) & + cmd_buf_cpu_va[methodSize++] = (u64_hi32(src_paddr) & NVGPU_CE_UPPER_ADDRESS_OFFSET_MASK); - cmd_buf_cpu_va[methodSize++] = (u64_lo32(src_buf) & + cmd_buf_cpu_va[methodSize++] = (u64_lo32(src_paddr) & NVGPU_CE_LOWER_ADDRESS_OFFSET_MASK); cmd_buf_cpu_va[methodSize++] = 0x20018098; @@ -275,9 +285,9 @@ static u32 nvgpu_prepare_ce_op(u32 *cmd_buf_cpu_va, /* setup the destination/output */ cmd_buf_cpu_va[methodSize++] = 0x20068102; - cmd_buf_cpu_va[methodSize++] = (u64_hi32(dst_buf) & + cmd_buf_cpu_va[methodSize++] = (u64_hi32(dst_paddr) & NVGPU_CE_UPPER_ADDRESS_OFFSET_MASK); - cmd_buf_cpu_va[methodSize++] = (u64_lo32(dst_buf) & + cmd_buf_cpu_va[methodSize++] = (u64_lo32(dst_paddr) & NVGPU_CE_LOWER_ADDRESS_OFFSET_MASK); /* Pitch in/out */ cmd_buf_cpu_va[methodSize++] = width; @@ -318,8 +328,8 @@ static u32 nvgpu_prepare_ce_op(u32 *cmd_buf_cpu_va, return methodSize; } -u32 nvgpu_ce_prepare_submit(u64 src_buf, - u64 dst_buf, +u32 nvgpu_ce_prepare_submit(u64 src_paddr, + u64 dst_paddr, u64 size, u32 *cmd_buf_cpu_va, u32 payload, @@ -364,14 +374,14 @@ u32 nvgpu_ce_prepare_submit(u64 src_buf, if (low != 0U) { /* do the low bytes in one long line */ methodSize += nvgpu_prepare_ce_op(&cmd_buf_cpu_va[methodSize], - src_buf, dst_buf, + src_paddr, dst_paddr, nvgpu_safe_cast_u64_to_u32(low), 1, payload, mode_transfer, launch_flags); } if (hi != 0U) { /* do the high bytes in many 2G lines */ methodSize += nvgpu_prepare_ce_op(&cmd_buf_cpu_va[methodSize], - src_buf + low, dst_buf + low, + src_paddr + low, dst_paddr + low, 0x80000000ULL, nvgpu_safe_cast_u64_to_u32(hi), payload, mode_transfer, launch_flags); } diff --git a/drivers/gpu/nvgpu/common/ce/ce_priv.h b/drivers/gpu/nvgpu/common/ce/ce_priv.h index 16bc0e60b..682c4c836 100644 --- a/drivers/gpu/nvgpu/common/ce/ce_priv.h +++ b/drivers/gpu/nvgpu/common/ce/ce_priv.h @@ -70,8 +70,8 @@ nvgpu_ce_gpu_ctx_from_list(struct nvgpu_list_node *node) ((uintptr_t)node - offsetof(struct nvgpu_ce_gpu_ctx, list)); }; -u32 nvgpu_ce_prepare_submit(u64 src_buf, - u64 dst_buf, +u32 nvgpu_ce_prepare_submit(u64 src_paddr, + u64 dst_paddr, u64 size, u32 *cmd_buf_cpu_va, u32 payload, diff --git a/drivers/gpu/nvgpu/include/nvgpu/ce_app.h b/drivers/gpu/nvgpu/include/nvgpu/ce_app.h index 5b5678243..ddbd686b5 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/ce_app.h +++ b/drivers/gpu/nvgpu/include/nvgpu/ce_app.h @@ -32,6 +32,9 @@ struct nvgpu_fence_type; /* CE command utility macros */ #define NVGPU_CE_LOWER_ADDRESS_OFFSET_MASK U32_MAX #define NVGPU_CE_UPPER_ADDRESS_OFFSET_MASK 0xffU +#define NVGPU_CE_MAX_ADDRESS \ + ((U64(NVGPU_CE_UPPER_ADDRESS_OFFSET_MASK) << 32U) | \ + U64(NVGPU_CE_LOWER_ADDRESS_OFFSET_MASK)) #define NVGPU_CE_MAX_INFLIGHT_JOBS 32U @@ -94,8 +97,8 @@ void nvgpu_ce_app_delete_context(struct gk20a *g, u32 ce_ctx_id); int nvgpu_ce_execute_ops(struct gk20a *g, u32 ce_ctx_id, - u64 src_buf, - u64 dst_buf, + u64 src_paddr, + u64 dst_paddr, u64 size, u32 payload, u32 launch_flags,