Add length check for ras command output buffer.

Signed-off-by: YiPeng Chai <[email protected]>
---
 .../gpu/drm/amd/ras/ras_mgr/amdgpu_ras_cmd.c  |  8 ++++---
 .../drm/amd/ras/ras_mgr/amdgpu_virt_ras_cmd.c |  5 +++--
 drivers/gpu/drm/amd/ras/rascore/ras_cmd.c     | 22 ++++++++++++++-----
 3 files changed, 24 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_cmd.c 
b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_cmd.c
index cb6498c30834..c22e53e84207 100644
--- a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_cmd.c
+++ b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_ras_cmd.c
@@ -139,7 +139,8 @@ static int amdgpu_ras_get_ras_safe_fb_addr_ranges(struct 
ras_core_context *ras_c
        struct amdgpu_mem_partition_info *mem_ranges;
        uint32_t i = 0;
 
-       if (cmd->input_size != sizeof(*input_data))
+       if ((cmd->input_size != sizeof(*input_data)) ||
+               (cmd->output_buf_size < sizeof(*ranges)))
                return RAS_CMD__ERROR_INVALID_INPUT_DATA;
 
        mem_ranges = adev->gmc.mem_partitions;
@@ -207,7 +208,8 @@ static int amdgpu_ras_translate_fb_address(struct 
ras_core_context *ras_core,
                        (struct ras_cmd_translate_fb_address_rsp 
*)cmd->output_buff_raw;
        int ret = RAS_CMD__ERROR_GENERIC;
 
-       if (cmd->input_size != sizeof(struct ras_cmd_translate_fb_address_req))
+       if ((cmd->input_size != sizeof(struct 
ras_cmd_translate_fb_address_req)) ||
+               (cmd->output_buf_size < sizeof(*rsp_buff)))
                return RAS_CMD__ERROR_INVALID_INPUT_SIZE;
 
        if ((req_buff->src_addr_type >= RAS_FB_ADDR_UNKNOWN) ||
@@ -279,7 +281,7 @@ int amdgpu_ras_submit_cmd(struct ras_core_context 
*ras_core, struct ras_cmd_ctx
 
        cmd->cmd_res = res;
 
-       if (cmd->output_size > cmd->output_buf_size) {
+       if (!res && (cmd->output_size > cmd->output_buf_size)) {
                RAS_DEV_ERR(cmd_core->dev,
                        "Output size 0x%x exceeds output buffer size 0x%x!\n",
                        cmd->output_size, cmd->output_buf_size);
diff --git a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_virt_ras_cmd.c 
b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_virt_ras_cmd.c
index 4775a56e47dc..b8e9442b2ca5 100644
--- a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_virt_ras_cmd.c
+++ b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_virt_ras_cmd.c
@@ -278,7 +278,8 @@ static int amdgpu_virt_ras_get_cper_records(struct 
ras_core_context *ras_core,
        uint8_t *out_buf;
        int ret = 0, i, count;
 
-       if (cmd->input_size != sizeof(struct ras_cmd_cper_record_req))
+       if (cmd->input_size != sizeof(struct ras_cmd_cper_record_req) ||
+               (cmd->output_buf_size < sizeof(*rsp)))
                return RAS_CMD__ERROR_INVALID_INPUT_SIZE;
 
        if (!req->buf_size || !req->buf_ptr || !req->cper_num)
@@ -491,7 +492,7 @@ int amdgpu_virt_ras_handle_cmd(struct ras_core_context 
*ras_core,
 
        cmd->cmd_res = res;
 
-       if (cmd->output_size > cmd->output_buf_size) {
+       if (!res && (cmd->output_size > cmd->output_buf_size)) {
                RAS_DEV_ERR(ras_core->dev,
                        "Output data size 0x%x exceeds buffer size 0x%x!\n",
                        cmd->output_size, cmd->output_buf_size);
diff --git a/drivers/gpu/drm/amd/ras/rascore/ras_cmd.c 
b/drivers/gpu/drm/amd/ras/rascore/ras_cmd.c
index 1136db9e29c4..5b7a36596b02 100644
--- a/drivers/gpu/drm/amd/ras/rascore/ras_cmd.c
+++ b/drivers/gpu/drm/amd/ras/rascore/ras_cmd.c
@@ -38,7 +38,8 @@ static int ras_get_block_ecc_info(struct ras_core_context 
*ras_core,
        struct ras_ecc_count err_data;
        int ret;
 
-       if (cmd->input_size != sizeof(struct ras_cmd_block_ecc_info_req))
+       if ((cmd->input_size != sizeof(struct ras_cmd_block_ecc_info_req)) ||
+               (cmd->output_buf_size < sizeof(*output_data)))
                return RAS_CMD__ERROR_INVALID_INPUT_SIZE;
 
        memset(&err_data, 0, sizeof(err_data));
@@ -122,7 +123,8 @@ static int ras_cmd_get_bad_pages(struct ras_core_context 
*ras_core,
                        (struct ras_cmd_bad_pages_info_rsp 
*)cmd->output_buff_raw;
        int ret;
 
-       if (cmd->input_size != sizeof(struct ras_cmd_bad_pages_info_req))
+       if ((cmd->input_size != sizeof(struct ras_cmd_bad_pages_info_req)) ||
+               (cmd->output_buf_size < sizeof(*output_data)))
                return RAS_CMD__ERROR_INVALID_INPUT_SIZE;
 
        ret = ras_cmd_get_group_bad_pages(ras_core, input_data->group_index, 
output_data);
@@ -177,7 +179,8 @@ static int ras_cmd_get_cper_snapshot(struct 
ras_core_context *ras_core,
                        (struct ras_cmd_cper_snapshot_rsp 
*)cmd->output_buff_raw;
        struct ras_log_batch_overview overview;
 
-       if (cmd->input_size != sizeof(struct ras_cmd_cper_snapshot_req))
+       if ((cmd->input_size != sizeof(struct ras_cmd_cper_snapshot_req)) ||
+               (cmd->output_buf_size < sizeof(*output_data)))
                return RAS_CMD__ERROR_INVALID_INPUT_SIZE;
 
        ras_log_ring_get_batch_overview(ras_core, &overview);
@@ -206,7 +209,8 @@ static int ras_cmd_get_cper_records(struct ras_core_context 
*ras_core,
        uint8_t *buffer;
        int ret = 0, i, count;
 
-       if (cmd->input_size != sizeof(struct ras_cmd_cper_record_req))
+       if ((cmd->input_size != sizeof(struct ras_cmd_cper_record_req)) ||
+               (cmd->output_buf_size < sizeof(*rsp)))
                return RAS_CMD__ERROR_INVALID_INPUT_SIZE;
 
        if (!req->buf_size || !req->buf_ptr || !req->cper_num)
@@ -264,7 +268,8 @@ static int ras_cmd_get_batch_trace_snapshot(struct 
ras_core_context *ras_core,
        struct ras_log_batch_overview overview;
 
 
-       if (cmd->input_size != sizeof(struct ras_cmd_batch_trace_snapshot_req))
+       if ((cmd->input_size != sizeof(struct 
ras_cmd_batch_trace_snapshot_req)) ||
+               (cmd->output_buf_size < sizeof(*rsp)))
                return RAS_CMD__ERROR_INVALID_INPUT_SIZE;
 
        ras_log_ring_get_batch_overview(ras_core, &overview);
@@ -292,7 +297,8 @@ static int ras_cmd_get_batch_trace_records(struct 
ras_core_context *ras_core,
        uint64_t id;
        bool completed = false;
 
-       if (cmd->input_size != sizeof(struct ras_cmd_batch_trace_record_req))
+       if ((cmd->input_size != sizeof(struct ras_cmd_batch_trace_record_req)) 
||
+               (cmd->output_buf_size < sizeof(*output_data)))
                return RAS_CMD__ERROR_INVALID_INPUT_SIZE;
 
        if ((!input_data->batch_num) || (input_data->batch_num > 
RAS_CMD_MAX_BATCH_NUM))
@@ -423,6 +429,10 @@ static int ras_cmd_inject_error(struct ras_core_context 
*ras_core,
                .value = req->method,
        };
 
+       if ((cmd->input_size != sizeof(*req)) ||
+               (cmd->output_buf_size < sizeof(*output_data)))
+               return RAS_CMD__ERROR_INVALID_INPUT_SIZE;
+
        ret = ras_psp_trigger_error(ras_core, &block_info, req->instance_mask);
        if (!ret) {
                output_data->version = 0;
-- 
2.43.0

Reply via email to