Commit 1972e324 authored by Yunfei Dong's avatar Yunfei Dong Committed by Mauro Carvalho Chehab

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

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: 27a274db ("[media] vcodec: mediatek: Add Mediatek VP8 Video Encoder Driver")
Signed-off-by: default avatarYunfei Dong <yunfei.dong@mediatek.com>
Reported-by: default avatarSteve Cho <stevecho@google.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
parent 655b86e5
......@@ -123,6 +123,7 @@ struct mtk_enc_params {
* @xfer_func: enum v4l2_xfer_func, colorspace transfer function
*
* @q_mutex: vb2_queue mutex.
* @vpu_inst: vpu instance pointer.
*/
struct mtk_vcodec_enc_ctx {
enum mtk_instance_type type;
......@@ -156,6 +157,7 @@ struct mtk_vcodec_enc_ctx {
enum v4l2_xfer_func xfer_func;
struct mutex q_mutex;
void *vpu_inst;
};
/**
......
......@@ -42,19 +42,46 @@ static void handle_enc_encode_msg(struct venc_vpu_inst *vpu, const void *data)
vpu->is_key_frm = msg->is_key_frm;
}
static bool vpu_enc_check_ap_inst(struct mtk_vcodec_enc_dev *enc_dev, struct venc_vpu_inst *vpu)
{
struct mtk_vcodec_enc_ctx *ctx;
int ret = false;
list_for_each_entry(ctx, &enc_dev->ctx_list, list) {
if (!IS_ERR_OR_NULL(ctx) && ctx->vpu_inst == vpu) {
ret = true;
break;
}
}
return ret;
}
static void vpu_enc_ipi_handler(void *data, unsigned int len, void *priv)
{
struct mtk_vcodec_enc_dev *enc_dev;
const struct venc_vpu_ipi_msg_common *msg = data;
struct venc_vpu_inst *vpu =
(struct venc_vpu_inst *)(unsigned long)msg->venc_inst;
struct venc_vpu_inst *vpu;
enc_dev = (struct mtk_vcodec_enc_dev *)priv;
vpu = (struct venc_vpu_inst *)(unsigned long)msg->venc_inst;
if (!priv || !vpu) {
pr_err(MTK_DBG_V4L2_STR "venc_inst is NULL, did the SCP hang or crash?");
return;
}
mtk_venc_debug(vpu->ctx, "msg_id %x inst %p status %d", msg->msg_id, vpu, msg->status);
if (!vpu_enc_check_ap_inst(enc_dev, vpu) || msg->msg_id < VPU_IPIMSG_ENC_INIT_DONE ||
msg->msg_id > VPU_IPIMSG_ENC_DEINIT_DONE) {
mtk_v4l2_venc_err(vpu->ctx, "venc msg id not correctly => 0x%x", msg->msg_id);
vpu->failure = -EINVAL;
goto error;
}
vpu->signaled = 1;
vpu->failure = (msg->status != VENC_IPI_MSG_STATUS_OK);
if (vpu->failure) {
mtk_venc_err(vpu->ctx, "vpu enc status failure %d", vpu->failure);
return;
goto error;
}
switch (msg->msg_id) {
......@@ -72,6 +99,9 @@ static void vpu_enc_ipi_handler(void *data, unsigned int len, void *priv)
mtk_venc_err(vpu->ctx, "unknown msg id %x", msg->msg_id);
break;
}
error:
vpu->signaled = 1;
}
static int vpu_enc_send_msg(struct venc_vpu_inst *vpu, void *msg,
......@@ -105,6 +135,7 @@ int vpu_enc_init(struct venc_vpu_inst *vpu)
init_waitqueue_head(&vpu->wq_hd);
vpu->signaled = 0;
vpu->failure = 0;
vpu->ctx->vpu_inst = vpu;
status = mtk_vcodec_fw_ipi_register(vpu->ctx->dev->fw_handler, vpu->id,
vpu_enc_ipi_handler, "venc", NULL);
......
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