diff options
| author | Mika Liljeberg <mliljeberg@nvidia.com> | 2016-09-15 13:49:07 -0400 |
|---|---|---|
| committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2016-09-16 09:47:04 -0400 |
| commit | 777fe8d46a465893d16ac6a5662859cd95737dfd (patch) | |
| tree | 418aee1f1147654725277d0109d8a551267871cf | |
| parent | 938c07bfbc2553a2b937111c1d82c2d89b241cef (diff) | |
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 <mliljeberg@nvidia.com>
Reviewed-on: http://git-master/r/1221429
GVS: Gerrit_Virtual_Submit
Reviewed-by: Pekka Pessi <ppessi@nvidia.com>
| -rw-r--r-- | drivers/platform/tegra/rtcpu/vi-notify.c | 26 |
1 files 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 { | |||
| 77 | }; | 77 | }; |
| 78 | 78 | ||
| 79 | static void tegra_ivc_vi_notify_process(struct tegra_ivc_channel *chan, | 79 | static void tegra_ivc_vi_notify_process(struct tegra_ivc_channel *chan, |
| 80 | const struct vi_notify_msg_ex *msg) | 80 | const struct vi_notify_msg_ex *msg, |
| 81 | size_t len) | ||
| 81 | { | 82 | { |
| 82 | struct tegra_ivc_vi_notify *ivn = tegra_ivc_channel_get_drvdata(chan); | 83 | struct tegra_ivc_vi_notify *ivn = tegra_ivc_channel_get_drvdata(chan); |
| 83 | struct vi_notify_dev *vnd = ivn->vi_notify; | 84 | struct vi_notify_dev *vnd = ivn->vi_notify; |
| 84 | u32 mask; | 85 | u32 mask; |
| 85 | u8 ch; | 86 | u8 ch; |
| 86 | 87 | ||
| 88 | if (sizeof(*msg) > len) { | ||
| 89 | dev_warn(&chan->dev, "Invalid extended message.\n"); | ||
| 90 | return; | ||
| 91 | } | ||
| 92 | |||
| 87 | switch (msg->type) { | 93 | switch (msg->type) { |
| 88 | case VI_NOTIFY_MSG_ACK: | 94 | case VI_NOTIFY_MSG_ACK: |
| 89 | complete(&ivn->ack); | 95 | complete(&ivn->ack); |
| @@ -111,20 +117,12 @@ static void tegra_ivc_vi_notify_recv(struct tegra_ivc_channel *chan, | |||
| 111 | const void *data, size_t len) | 117 | const void *data, size_t len) |
| 112 | { | 118 | { |
| 113 | struct tegra_ivc_vi_notify *ivn = tegra_ivc_channel_get_drvdata(chan); | 119 | struct tegra_ivc_vi_notify *ivn = tegra_ivc_channel_get_drvdata(chan); |
| 114 | const struct vi_notify_msg *entries = data; | 120 | const struct vi_notify_msg *msg = data; |
| 115 | 121 | ||
| 116 | /* Receive VI Notify events */ | 122 | if (len >= sizeof(*msg) && VI_NOTIFY_TAG_VALID(msg->tag)) |
| 117 | while (len >= sizeof(*entries)) { | 123 | vi_notify_dev_recv(ivn->vi_notify, msg); |
| 118 | if (!entries->tag) | 124 | else |
| 119 | break; | 125 | tegra_ivc_vi_notify_process(chan, data, len); |
| 120 | if (VI_NOTIFY_TAG_VALID(entries->tag)) | ||
| 121 | vi_notify_dev_recv(ivn->vi_notify, entries); | ||
| 122 | else | ||
| 123 | tegra_ivc_vi_notify_process(chan, data); | ||
| 124 | |||
| 125 | entries++; | ||
| 126 | len -= sizeof(*entries); | ||
| 127 | } | ||
| 128 | } | 126 | } |
| 129 | 127 | ||
| 130 | static void tegra_ivc_channel_vi_notify_process(struct tegra_ivc_channel *chan) | 128 | static void tegra_ivc_channel_vi_notify_process(struct tegra_ivc_channel *chan) |
