DivestOS/Patches/Linux_CVEs/CVE-2016-5864/ANY/0.patch

133 lines
4.5 KiB
Diff
Raw Normal View History

From cbc21ceb69cb7bca0643423a7ca982abce3ce50a Mon Sep 17 00:00:00 2001
From: Vidyakumar Athota <vathota@codeaurora.org>
Date: Wed, 4 Jan 2017 13:32:50 -0800
Subject: soc: qcom: check userspace buffer size in write()
Add checks to make sure userspace buffer is valid before
it is used. Add upper limit for glink channels and number
of intents allowed.
Change-Id: I9b8f2e47aada7922ba22cbb010176bf36a9d6288
Signed-off-by: Vidyakumar Athota <vathota@codeaurora.org>
---
drivers/soc/qcom/wcd-dsp-glink.c | 51 ++++++++++++++++++++++++++++++++--------
1 file changed, 41 insertions(+), 10 deletions(-)
diff --git a/drivers/soc/qcom/wcd-dsp-glink.c b/drivers/soc/qcom/wcd-dsp-glink.c
index 27e66dc..1ceded4 100644
--- a/drivers/soc/qcom/wcd-dsp-glink.c
+++ b/drivers/soc/qcom/wcd-dsp-glink.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -25,8 +25,10 @@
#include "sound/wcd-dsp-glink.h"
#define WDSP_GLINK_DRIVER_NAME "wcd-dsp-glink"
-#define WDSP_MAX_WRITE_SIZE (512 * 1024)
+#define WDSP_MAX_WRITE_SIZE (256 * 1024)
#define WDSP_MAX_READ_SIZE (4 * 1024)
+#define WDSP_MAX_NO_OF_INTENTS (20)
+#define WDSP_MAX_NO_OF_CHANNELS (10)
#define MINOR_NUMBER_COUNT 1
#define WDSP_EDGE "wdsp"
@@ -532,15 +534,30 @@ static int wdsp_glink_ch_info_init(struct wdsp_glink_priv *wpriv,
payload = (u8 *)pkt->payload;
no_of_channels = pkt->no_of_channels;
+ if (no_of_channels > WDSP_MAX_NO_OF_CHANNELS) {
+ dev_info(wpriv->dev, "%s: no_of_channels = %d are limited to %d\n",
+ __func__, no_of_channels, WDSP_MAX_NO_OF_CHANNELS);
+ no_of_channels = WDSP_MAX_NO_OF_CHANNELS;
+ }
ch = kcalloc(no_of_channels, sizeof(struct wdsp_glink_ch *),
GFP_KERNEL);
if (!ch) {
ret = -ENOMEM;
goto done;
}
+ wpriv->ch = ch;
+ wpriv->no_of_channels = no_of_channels;
for (i = 0; i < no_of_channels; i++) {
ch_cfg = (struct wdsp_glink_ch_cfg *)payload;
+
+ if (ch_cfg->no_of_intents > WDSP_MAX_NO_OF_INTENTS) {
+ dev_err(wpriv->dev, "%s: Invalid no_of_intents = %d\n",
+ __func__, ch_cfg->no_of_intents);
+ ret = -EINVAL;
+ goto err_ch_mem;
+ }
+
ch_cfg_size = sizeof(struct wdsp_glink_ch_cfg) +
(sizeof(u32) * ch_cfg->no_of_intents);
ch_size = sizeof(struct wdsp_glink_ch) +
@@ -564,8 +581,6 @@ static int wdsp_glink_ch_info_init(struct wdsp_glink_priv *wpriv,
INIT_WORK(&ch[i]->lcl_ch_cls_wrk, wdsp_glink_lcl_ch_cls_wrk);
init_waitqueue_head(&ch[i]->ch_connect_wait);
}
- wpriv->ch = ch;
- wpriv->no_of_channels = no_of_channels;
INIT_WORK(&wpriv->ch_open_cls_wrk, wdsp_glink_ch_open_cls_wrk);
@@ -746,15 +761,17 @@ static ssize_t wdsp_glink_write(struct file *file, const char __user *buf,
goto done;
}
- dev_dbg(wpriv->dev, "%s: count = %zd\n", __func__, count);
-
- if (count > WDSP_MAX_WRITE_SIZE) {
- dev_info(wpriv->dev, "%s: count = %zd is more than WDSP_MAX_WRITE_SIZE\n",
+ if ((count < sizeof(struct wdsp_write_pkt)) ||
+ (count > WDSP_MAX_WRITE_SIZE)) {
+ dev_err(wpriv->dev, "%s: Invalid count = %zd\n",
__func__, count);
- count = WDSP_MAX_WRITE_SIZE;
+ ret = -EINVAL;
+ goto done;
}
- tx_buf_size = count + sizeof(struct wdsp_glink_tx_buf);
+ dev_dbg(wpriv->dev, "%s: count = %zd\n", __func__, count);
+
+ tx_buf_size = WDSP_MAX_WRITE_SIZE + sizeof(struct wdsp_glink_tx_buf);
tx_buf = kzalloc(tx_buf_size, GFP_KERNEL);
if (!tx_buf) {
ret = -ENOMEM;
@@ -772,6 +789,13 @@ static ssize_t wdsp_glink_write(struct file *file, const char __user *buf,
wpkt = (struct wdsp_write_pkt *)tx_buf->buf;
switch (wpkt->pkt_type) {
case WDSP_REG_PKT:
+ if (count <= (sizeof(struct wdsp_write_pkt) +
+ sizeof(struct wdsp_reg_pkt))) {
+ dev_err(wpriv->dev, "%s: Invalid reg pkt size = %zd\n",
+ __func__, count);
+ ret = -EINVAL;
+ goto free_buf;
+ }
ret = wdsp_glink_ch_info_init(wpriv,
(struct wdsp_reg_pkt *)wpkt->payload);
if (IS_ERR_VALUE(ret))
@@ -794,6 +818,13 @@ static ssize_t wdsp_glink_write(struct file *file, const char __user *buf,
kfree(tx_buf);
break;
case WDSP_CMD_PKT:
+ if (count <= (sizeof(struct wdsp_write_pkt) +
+ sizeof(struct wdsp_cmd_pkt))) {
+ dev_err(wpriv->dev, "%s: Invalid cmd pkt size = %zd\n",
+ __func__, count);
+ ret = -EINVAL;
+ goto free_buf;
+ }
mutex_lock(&wpriv->glink_mutex);
if (wpriv->glink_state.link_state == GLINK_LINK_STATE_DOWN) {
mutex_unlock(&wpriv->glink_mutex);
--
cgit v1.1