Commit 655b86e5 authored by Yunfei Dong's avatar Yunfei Dong Committed by Mauro Carvalho Chehab

media: mediatek: vcodec: Fix possible invalid memory access for decoder

The vpu maybe null pointer or unreasonable value when scp crash, need to
validate that the vpu pointer and the vpu instance within this context is
valid in case of leading to kernel reboot.

Fixes: 590577a4 ("[media] vcodec: mediatek: Add Mediatek V4L2 Video Decoder Driver")
Signed-off-by: default avatarYunfei Dong <yunfei.dong@mediatek.com>
Reported-by: default avatarSteve Cho <stevecho@google.com>
Reviewed-by: default avatarNicolas Dufresne <nicolas.dufresne@collabora.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
parent 9d86be9b
...@@ -161,6 +161,7 @@ struct mtk_vcodec_dec_pdata { ...@@ -161,6 +161,7 @@ struct mtk_vcodec_dec_pdata {
* @hw_id: hardware index used to identify different hardware. * @hw_id: hardware index used to identify different hardware.
* *
* @msg_queue: msg queue used to store lat buffer information. * @msg_queue: msg queue used to store lat buffer information.
* @vpu_inst: vpu instance pointer.
* *
* @is_10bit_bitstream: set to true if it's 10bit bitstream * @is_10bit_bitstream: set to true if it's 10bit bitstream
*/ */
...@@ -205,6 +206,7 @@ struct mtk_vcodec_dec_ctx { ...@@ -205,6 +206,7 @@ struct mtk_vcodec_dec_ctx {
int hw_id; int hw_id;
struct vdec_msg_queue msg_queue; struct vdec_msg_queue msg_queue;
void *vpu_inst;
bool is_10bit_bitstream; bool is_10bit_bitstream;
}; };
......
...@@ -72,6 +72,21 @@ static void handle_get_param_msg_ack(const struct vdec_vpu_ipi_get_param_ack *ms ...@@ -72,6 +72,21 @@ static void handle_get_param_msg_ack(const struct vdec_vpu_ipi_get_param_ack *ms
} }
} }
static bool vpu_dec_check_ap_inst(struct mtk_vcodec_dec_dev *dec_dev, struct vdec_vpu_inst *vpu)
{
struct mtk_vcodec_dec_ctx *ctx;
int ret = false;
list_for_each_entry(ctx, &dec_dev->ctx_list, list) {
if (!IS_ERR_OR_NULL(ctx) && ctx->vpu_inst == vpu) {
ret = true;
break;
}
}
return ret;
}
/* /*
* vpu_dec_ipi_handler - Handler for VPU ipi message. * vpu_dec_ipi_handler - Handler for VPU ipi message.
* *
...@@ -84,44 +99,51 @@ static void handle_get_param_msg_ack(const struct vdec_vpu_ipi_get_param_ack *ms ...@@ -84,44 +99,51 @@ static void handle_get_param_msg_ack(const struct vdec_vpu_ipi_get_param_ack *ms
*/ */
static void vpu_dec_ipi_handler(void *data, unsigned int len, void *priv) static void vpu_dec_ipi_handler(void *data, unsigned int len, void *priv)
{ {
struct mtk_vcodec_dec_dev *dec_dev;
const struct vdec_vpu_ipi_ack *msg = data; const struct vdec_vpu_ipi_ack *msg = data;
struct vdec_vpu_inst *vpu = (struct vdec_vpu_inst *) struct vdec_vpu_inst *vpu;
(unsigned long)msg->ap_inst_addr;
if (!vpu) { dec_dev = (struct mtk_vcodec_dec_dev *)priv;
mtk_v4l2_vdec_err(vpu->ctx, "ap_inst_addr is NULL, did the SCP hang or crash?"); vpu = (struct vdec_vpu_inst *)(unsigned long)msg->ap_inst_addr;
if (!priv || !vpu) {
pr_err(MTK_DBG_V4L2_STR "ap_inst_addr is NULL, did the SCP hang or crash?");
return; return;
} }
mtk_vdec_debug(vpu->ctx, "+ id=%X", msg->msg_id); if (!vpu_dec_check_ap_inst(dec_dev, vpu) || msg->msg_id < VPU_IPIMSG_DEC_INIT_ACK ||
msg->msg_id > VPU_IPIMSG_DEC_GET_PARAM_ACK) {
mtk_v4l2_vdec_err(vpu->ctx, "vdec msg id not correctly => 0x%x", msg->msg_id);
vpu->failure = -EINVAL;
goto error;
}
vpu->failure = msg->status; vpu->failure = msg->status;
vpu->signaled = 1; if (msg->status != 0)
goto error;
if (msg->status == 0) { switch (msg->msg_id) {
switch (msg->msg_id) { case VPU_IPIMSG_DEC_INIT_ACK:
case VPU_IPIMSG_DEC_INIT_ACK: handle_init_ack_msg(data);
handle_init_ack_msg(data); break;
break;
case VPU_IPIMSG_DEC_START_ACK: case VPU_IPIMSG_DEC_START_ACK:
case VPU_IPIMSG_DEC_END_ACK: case VPU_IPIMSG_DEC_END_ACK:
case VPU_IPIMSG_DEC_DEINIT_ACK: case VPU_IPIMSG_DEC_DEINIT_ACK:
case VPU_IPIMSG_DEC_RESET_ACK: case VPU_IPIMSG_DEC_RESET_ACK:
case VPU_IPIMSG_DEC_CORE_ACK: case VPU_IPIMSG_DEC_CORE_ACK:
case VPU_IPIMSG_DEC_CORE_END_ACK: case VPU_IPIMSG_DEC_CORE_END_ACK:
break; break;
case VPU_IPIMSG_DEC_GET_PARAM_ACK: case VPU_IPIMSG_DEC_GET_PARAM_ACK:
handle_get_param_msg_ack(data); handle_get_param_msg_ack(data);
break; break;
default: default:
mtk_vdec_err(vpu->ctx, "invalid msg=%X", msg->msg_id); mtk_vdec_err(vpu->ctx, "invalid msg=%X", msg->msg_id);
break; break;
}
} }
mtk_vdec_debug(vpu->ctx, "- id=%X", msg->msg_id); error:
vpu->signaled = 1;
} }
static int vcodec_vpu_send_msg(struct vdec_vpu_inst *vpu, void *msg, int len) static int vcodec_vpu_send_msg(struct vdec_vpu_inst *vpu, void *msg, int len)
...@@ -182,9 +204,10 @@ int vpu_dec_init(struct vdec_vpu_inst *vpu) ...@@ -182,9 +204,10 @@ int vpu_dec_init(struct vdec_vpu_inst *vpu)
init_waitqueue_head(&vpu->wq); init_waitqueue_head(&vpu->wq);
vpu->handler = vpu_dec_ipi_handler; vpu->handler = vpu_dec_ipi_handler;
vpu->ctx->vpu_inst = vpu;
err = mtk_vcodec_fw_ipi_register(vpu->ctx->dev->fw_handler, vpu->id, err = mtk_vcodec_fw_ipi_register(vpu->ctx->dev->fw_handler, vpu->id,
vpu->handler, "vdec", NULL); vpu->handler, "vdec", vpu->ctx->dev);
if (err) { if (err) {
mtk_vdec_err(vpu->ctx, "vpu_ipi_register fail status=%d", err); mtk_vdec_err(vpu->ctx, "vpu_ipi_register fail status=%d", err);
return err; return err;
...@@ -193,7 +216,7 @@ int vpu_dec_init(struct vdec_vpu_inst *vpu) ...@@ -193,7 +216,7 @@ int vpu_dec_init(struct vdec_vpu_inst *vpu)
if (vpu->ctx->dev->vdec_pdata->hw_arch == MTK_VDEC_LAT_SINGLE_CORE) { if (vpu->ctx->dev->vdec_pdata->hw_arch == MTK_VDEC_LAT_SINGLE_CORE) {
err = mtk_vcodec_fw_ipi_register(vpu->ctx->dev->fw_handler, err = mtk_vcodec_fw_ipi_register(vpu->ctx->dev->fw_handler,
vpu->core_id, vpu->handler, vpu->core_id, vpu->handler,
"vdec", NULL); "vdec", vpu->ctx->dev);
if (err) { if (err) {
mtk_vdec_err(vpu->ctx, "vpu_ipi_register core fail status=%d", err); mtk_vdec_err(vpu->ctx, "vpu_ipi_register core fail status=%d", err);
return err; return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment