From e948d6199e29dcd423b5b2e0e887201dd46ceec9 Mon Sep 17 00:00:00 2001 From: George Shen Date: Wed, 18 Mar 2020 15:21:22 -0700 Subject: [PATCH] msm: cvp: Validate buffer config in HFI packet Validates buffer configuration in HFI packet structure before kernel driver maps them in IOMMU. Change-Id: I7075cc2fdead7f46d52b174a3c45cd07a8ac24af Signed-off-by: George Shen --- drivers/media/platform/msm/cvp/cvp_hfi.c | 7 +- drivers/media/platform/msm/cvp/cvp_hfi.h | 3 +- drivers/media/platform/msm/cvp/cvp_hfi_api.h | 3 +- .../platform/msm/cvp/hfi_response_handler.c | 64 +++++++++++-------- drivers/media/platform/msm/cvp/msm_cvp.c | 9 ++- drivers/media/platform/msm/cvp/msm_cvp.h | 18 ++++++ 6 files changed, 71 insertions(+), 33 deletions(-) diff --git a/drivers/media/platform/msm/cvp/cvp_hfi.c b/drivers/media/platform/msm/cvp/cvp_hfi.c index 47225d63e80f..b2fe4e8a9daf 100644 --- a/drivers/media/platform/msm/cvp/cvp_hfi.c +++ b/drivers/media/platform/msm/cvp/cvp_hfi.c @@ -2976,10 +2976,10 @@ static int __response_handler(struct iris_hfi_device *device) print_msg_hdr(hdr); rc = cvp_hfi_process_msg_packet(device->device_id, - (struct cvp_hal_msg_pkt_hdr *)raw_packet, info); + raw_packet, info); if (rc) { dprintk(CVP_WARN, - "Corrupt/unknown packet found, discarding\n"); + "Corrupt/unknown packet found, discarding\n"); --packet_count; continue; } else if (info->response_type == HAL_NO_RESP) { @@ -3097,6 +3097,7 @@ err_no_work: for (i = 0; !IS_ERR_OR_NULL(device->response_pkt) && i < num_responses; ++i) { struct msm_cvp_cb_info *r = &device->response_pkt[i]; + void *rsp = (void *)&r->response; if (!__core_in_valid_state(device)) { dprintk(CVP_ERR, @@ -3105,7 +3106,7 @@ err_no_work: } dprintk(CVP_DBG, "Processing response %d of %d, type %d\n", (i + 1), num_responses, r->response_type); - device->callback(r->response_type, &r->response); + device->callback(r->response_type, rsp); } /* We need re-enable the irq which was disabled in ISR handler */ diff --git a/drivers/media/platform/msm/cvp/cvp_hfi.h b/drivers/media/platform/msm/cvp/cvp_hfi.h index 9c6ff815a5cf..d7ff31d1aa57 100644 --- a/drivers/media/platform/msm/cvp/cvp_hfi.h +++ b/drivers/media/platform/msm/cvp/cvp_hfi.h @@ -201,8 +201,7 @@ struct msm_cvp_fw { }; int cvp_hfi_process_msg_packet(u32 device_id, - struct cvp_hal_msg_pkt_hdr *msg_hdr, - struct msm_cvp_cb_info *info); + void *msg_hdr, struct msm_cvp_cb_info *info); enum cvp_status cvp_hfi_process_sys_init_done_prop_read( struct cvp_hfi_msg_sys_init_done_packet *pkt, diff --git a/drivers/media/platform/msm/cvp/cvp_hfi_api.h b/drivers/media/platform/msm/cvp/cvp_hfi_api.h index 152d5a4effcf..585dad12d315 100644 --- a/drivers/media/platform/msm/cvp/cvp_hfi_api.h +++ b/drivers/media/platform/msm/cvp/cvp_hfi_api.h @@ -357,7 +357,8 @@ struct cvp_hfi_device { typedef void (*hfi_cmd_response_callback) (enum hal_command_response cmd, void *data); -typedef void (*msm_cvp_callback) (u32 response, void *callback); +typedef void (*msm_cvp_callback) (enum hal_command_response response, + void *callback); struct cvp_hfi_device *cvp_hfi_initialize(enum msm_cvp_hfi_type hfi_type, u32 device_id, struct msm_cvp_platform_resources *res, diff --git a/drivers/media/platform/msm/cvp/hfi_response_handler.c b/drivers/media/platform/msm/cvp/hfi_response_handler.c index 1a8b62e57d8c..6d5417feff23 100644 --- a/drivers/media/platform/msm/cvp/hfi_response_handler.c +++ b/drivers/media/platform/msm/cvp/hfi_response_handler.c @@ -116,9 +116,11 @@ static int hfi_process_session_error(u32 device_id, } static int hfi_process_event_notify(u32 device_id, - struct cvp_hfi_msg_event_notify_packet *pkt, - struct msm_cvp_cb_info *info) + void *hdr, struct msm_cvp_cb_info *info) { + struct cvp_hfi_msg_event_notify_packet *pkt = + (struct cvp_hfi_msg_event_notify_packet *)hdr; + dprintk(CVP_DBG, "Received: EVENT_NOTIFY\n"); if (pkt->size < sizeof(struct cvp_hfi_msg_event_notify_packet)) { @@ -147,9 +149,10 @@ static int hfi_process_event_notify(u32 device_id, } static int hfi_process_sys_init_done(u32 device_id, - struct cvp_hfi_msg_sys_init_done_packet *pkt, - struct msm_cvp_cb_info *info) + void *hdr, struct msm_cvp_cb_info *info) { + struct cvp_hfi_msg_sys_init_done_packet *pkt = + (struct cvp_hfi_msg_sys_init_done_packet *)hdr; struct msm_cvp_cb_cmd_done cmd_done = {0}; enum cvp_status status = CVP_ERR_NONE; @@ -224,9 +227,10 @@ enum cvp_status cvp_hfi_process_sys_init_done_prop_read( } static int hfi_process_session_init_done(u32 device_id, - struct cvp_hfi_msg_sys_session_init_done_packet *pkt, - struct msm_cvp_cb_info *info) + void *hdr, struct msm_cvp_cb_info *info) { + struct cvp_hfi_msg_sys_session_init_done_packet *pkt = + (struct cvp_hfi_msg_sys_session_init_done_packet *)hdr; struct msm_cvp_cb_cmd_done cmd_done = {0}; struct cvp_hal_session_init_done session_init_done = { {0} }; @@ -251,9 +255,10 @@ static int hfi_process_session_init_done(u32 device_id, return 0; } static int hfi_process_session_end_done(u32 device_id, - struct cvp_hfi_msg_sys_session_end_done_packet *pkt, - struct msm_cvp_cb_info *info) + void *hdr, struct msm_cvp_cb_info *info) { + struct cvp_hfi_msg_sys_session_end_done_packet *pkt = + (struct cvp_hfi_msg_sys_session_end_done_packet *)hdr; struct msm_cvp_cb_cmd_done cmd_done = {0}; dprintk(CVP_DBG, "RECEIVED: SESSION_END_DONE[%#x]\n", pkt->session_id); @@ -276,9 +281,10 @@ static int hfi_process_session_end_done(u32 device_id, } static int hfi_process_session_abort_done(u32 device_id, - struct cvp_hfi_msg_sys_session_abort_done_packet *pkt, - struct msm_cvp_cb_info *info) + void *hdr, struct msm_cvp_cb_info *info) { + struct cvp_hfi_msg_sys_session_abort_done_packet *pkt = + (struct cvp_hfi_msg_sys_session_abort_done_packet *)hdr; struct msm_cvp_cb_cmd_done cmd_done = {0}; dprintk(CVP_DBG, "RECEIVED: SESSION_ABORT_DONE[%#x]\n", @@ -302,9 +308,10 @@ static int hfi_process_session_abort_done(u32 device_id, } static int hfi_process_session_set_buf_done(u32 device_id, - struct cvp_hfi_msg_session_hdr *pkt, - struct msm_cvp_cb_info *info) + void *hdr, struct msm_cvp_cb_info *info) { + struct cvp_hfi_msg_session_hdr *pkt = + (struct cvp_hfi_msg_session_hdr *)hdr; struct msm_cvp_cb_cmd_done cmd_done = {0}; unsigned int pkt_size = get_msg_size(); @@ -328,9 +335,10 @@ static int hfi_process_session_set_buf_done(u32 device_id, } static int hfi_process_session_flush_done(u32 device_id, - struct cvp_hfi_msg_sys_session_flush_done_packet *pkt, - struct msm_cvp_cb_info *info) + void *hdr, struct msm_cvp_cb_info *info) { + struct cvp_hfi_msg_sys_session_flush_done_packet *pkt = + (struct cvp_hfi_msg_sys_session_flush_done_packet *)hdr; struct msm_cvp_cb_cmd_done cmd_done = {0}; dprintk(CVP_DBG, "RECEIVED: SESSION_FLUSH_DONE[%#x]\n", @@ -354,9 +362,10 @@ static int hfi_process_session_flush_done(u32 device_id, } static int hfi_process_session_rel_buf_done(u32 device_id, - struct cvp_hfi_msg_session_hdr *pkt, - struct msm_cvp_cb_info *info) + void *hdr, struct msm_cvp_cb_info *info) { + struct cvp_hfi_msg_session_hdr *pkt = + (struct cvp_hfi_msg_session_hdr *)hdr; struct msm_cvp_cb_cmd_done cmd_done = {0}; unsigned int pkt_size = get_msg_size(); @@ -380,9 +389,10 @@ static int hfi_process_session_rel_buf_done(u32 device_id, } static int hfi_process_session_cvp_operation_config(u32 device_id, - struct cvp_hfi_msg_session_op_cfg_packet *pkt, - struct msm_cvp_cb_info *info) + void *hdr, struct msm_cvp_cb_info *info) { + struct cvp_hfi_msg_session_op_cfg_packet *pkt = + (struct cvp_hfi_msg_session_op_cfg_packet *)hdr; struct msm_cvp_cb_cmd_done cmd_done = {0}; int signal; unsigned int conf_id, session_id, error_type; @@ -467,9 +477,10 @@ retry: } static int hfi_process_session_cvp_msg(u32 device_id, - struct cvp_hfi_msg_session_hdr *pkt, - struct msm_cvp_cb_info *info) + void *hdr, struct msm_cvp_cb_info *info) { + struct cvp_hfi_msg_session_hdr *pkt = + (struct cvp_hfi_msg_session_hdr *)hdr; struct cvp_session_msg *sess_msg; struct msm_cvp_inst *inst = NULL; struct msm_cvp_core *core; @@ -563,9 +574,10 @@ static void hfi_process_sys_get_prop_image_version( } static int hfi_process_sys_property_info(u32 device_id, - struct cvp_hfi_msg_sys_property_info_packet *pkt, - struct msm_cvp_cb_info *info) + void *hdr, struct msm_cvp_cb_info *info) { + struct cvp_hfi_msg_sys_property_info_packet *pkt = + (struct cvp_hfi_msg_sys_property_info_packet *)hdr; if (!pkt) { dprintk(CVP_ERR, "%s: invalid param\n", __func__); return -EINVAL; @@ -596,12 +608,12 @@ static int hfi_process_sys_property_info(u32 device_id, } -int cvp_hfi_process_msg_packet(u32 device_id, - struct cvp_hal_msg_pkt_hdr *msg_hdr, - struct msm_cvp_cb_info *info) +int cvp_hfi_process_msg_packet(u32 device_id, void *hdr, + struct msm_cvp_cb_info *info) { typedef int (*pkt_func_def)(u32, void *, struct msm_cvp_cb_info *info); pkt_func_def pkt_func = NULL; + struct cvp_hal_msg_pkt_hdr *msg_hdr = (struct cvp_hal_msg_pkt_hdr *)hdr; if (!info || !msg_hdr || msg_hdr->size < CVP_IFACEQ_MIN_PKT_SIZE) { dprintk(CVP_ERR, "%s: bad packet/packet size\n", @@ -659,5 +671,5 @@ int cvp_hfi_process_msg_packet(u32 device_id, } return pkt_func ? - pkt_func(device_id, (void *)msg_hdr, info) : -ENOTSUPP; + pkt_func(device_id, hdr, info) : -ENOTSUPP; } diff --git a/drivers/media/platform/msm/cvp/msm_cvp.c b/drivers/media/platform/msm/cvp/msm_cvp.c index 459356675b15..4992fce5a7f0 100644 --- a/drivers/media/platform/msm/cvp/msm_cvp.c +++ b/drivers/media/platform/msm/cvp/msm_cvp.c @@ -204,7 +204,10 @@ static int msm_cvp_session_process_hfi( offset = in_offset; buf_num = in_buf_num; } - + if (!is_buf_param_valid(buf_num, offset)) { + dprintk(CVP_ERR, "Incorrect buffer num and offset in cmd\n"); + return -EINVAL; + } pkt_type = in_pkt->pkt_data[1]; if (pkt_type == HFI_CMD_SESSION_CVP_SET_PERSIST_BUFFERS) rc = msm_cvp_map_user_persist(inst, in_pkt, offset, buf_num); @@ -741,6 +744,10 @@ static int msm_cvp_session_process_hfi_fence(struct msm_cvp_inst *inst, buf_num = cvp_hfi_defs[idx].buf_num; } + if (!is_buf_param_valid(buf_num, offset)) { + dprintk(CVP_ERR, "Incorrect buf num and offset in cmd\n"); + return -EINVAL; + } rc = msm_cvp_map_frame(inst, (struct cvp_kmd_hfi_packet *)pkt, offset, buf_num); if (rc) diff --git a/drivers/media/platform/msm/cvp/msm_cvp.h b/drivers/media/platform/msm/cvp/msm_cvp.h index 0e19ad8e9f87..06dba1990e4c 100644 --- a/drivers/media/platform/msm/cvp/msm_cvp.h +++ b/drivers/media/platform/msm/cvp/msm_cvp.h @@ -11,6 +11,24 @@ #include "msm_cvp_clocks.h" #include "msm_cvp_debug.h" #include "msm_cvp_dsp.h" + +static inline bool is_buf_param_valid(u32 buf_num, u32 offset) +{ + int max_buf_num; + + max_buf_num = sizeof(struct cvp_kmd_hfi_packet) / + sizeof(struct cvp_buf_type); + + if (buf_num > max_buf_num) + return false; + + if ((offset + buf_num * sizeof(struct cvp_buf_type)) > + sizeof(struct cvp_kmd_hfi_packet)) + return false; + + return true; +} + int msm_cvp_handle_syscall(struct msm_cvp_inst *inst, struct cvp_kmd_arg *arg); int msm_cvp_session_init(struct msm_cvp_inst *inst); int msm_cvp_session_deinit(struct msm_cvp_inst *inst);