From 777fe8d46a465893d16ac6a5662859cd95737dfd Mon Sep 17 00:00:00 2001 From: Mika Liljeberg Date: Thu, 15 Sep 2016 20:49:07 +0300 Subject: rtcpu: vi: fix message size handling Incorrect IVC message size handling may result in the driver attempting to process random data as a VI notify message. Code assumes that an IVC message from rtcpu contains an array of fixed size VI notify messages, whereas the rtcpu implementation only ever puts a single notify message into each IVC message. The size of the notify message may vary. Remove the erroneous processing loop and add size checks. Bug 1814523 Change-Id: I87f1772d2bcb16eabcc20726c2dd2fee22d66c25 Signed-off-by: Mika Liljeberg Reviewed-on: http://git-master/r/1221429 GVS: Gerrit_Virtual_Submit Reviewed-by: Pekka Pessi --- drivers/platform/tegra/rtcpu/vi-notify.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/platform/tegra/rtcpu/vi-notify.c b/drivers/platform/tegra/rtcpu/vi-notify.c index 85f168e75..c868ee593 100644 --- a/drivers/platform/tegra/rtcpu/vi-notify.c +++ b/drivers/platform/tegra/rtcpu/vi-notify.c @@ -77,13 +77,19 @@ struct tegra_ivc_vi_notify { }; static void tegra_ivc_vi_notify_process(struct tegra_ivc_channel *chan, - const struct vi_notify_msg_ex *msg) + const struct vi_notify_msg_ex *msg, + size_t len) { struct tegra_ivc_vi_notify *ivn = tegra_ivc_channel_get_drvdata(chan); struct vi_notify_dev *vnd = ivn->vi_notify; u32 mask; u8 ch; + if (sizeof(*msg) > len) { + dev_warn(&chan->dev, "Invalid extended message.\n"); + return; + } + switch (msg->type) { case VI_NOTIFY_MSG_ACK: complete(&ivn->ack); @@ -111,20 +117,12 @@ static void tegra_ivc_vi_notify_recv(struct tegra_ivc_channel *chan, const void *data, size_t len) { struct tegra_ivc_vi_notify *ivn = tegra_ivc_channel_get_drvdata(chan); - const struct vi_notify_msg *entries = data; + const struct vi_notify_msg *msg = data; - /* Receive VI Notify events */ - while (len >= sizeof(*entries)) { - if (!entries->tag) - break; - if (VI_NOTIFY_TAG_VALID(entries->tag)) - vi_notify_dev_recv(ivn->vi_notify, entries); - else - tegra_ivc_vi_notify_process(chan, data); - - entries++; - len -= sizeof(*entries); - } + if (len >= sizeof(*msg) && VI_NOTIFY_TAG_VALID(msg->tag)) + vi_notify_dev_recv(ivn->vi_notify, msg); + else + tegra_ivc_vi_notify_process(chan, data, len); } static void tegra_ivc_channel_vi_notify_process(struct tegra_ivc_channel *chan) -- cgit v1.2.2