blob: 1664e8f3757eb1116df4a91ca8d45dd5413c3bfa [file] [log] [blame]
From c0cef7a615b4b22c834f83dfe5e99b93737bf0ef Mon Sep 17 00:00:00 2001
From: Veera Sundaram Sankaran <veeras@codeaurora.org>
Date: Tue, 15 Mar 2016 18:42:27 -0700
Subject: [PATCH] msm: mdss: fix possible out-of-bounds and overflow issue in
mdp debugfs
There are few cases where the count argument passed by the user
space is not validated, which can potentially lead to out of bounds
or overflow issues. In some cases, kernel might copy more data than
what is requested. Add necessary checks to avoid such cases.
Change-Id: Ifa42fbd475665a0ca581c907ce5432584ea0e7ed
Signed-off-by: Veera Sundaram Sankaran <veeras@codeaurora.org>
---
drivers/video/msm/mdss/mdss_debug.c | 44 +++++++++++++++++++++----------------
1 file changed, 25 insertions(+), 19 deletions(-)
diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c
index 3b01bfc..e07aeeb 100644
--- a/drivers/video/msm/mdss/mdss_debug.c
+++ b/drivers/video/msm/mdss/mdss_debug.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2009-2016, 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
@@ -109,10 +109,10 @@ static ssize_t panel_debug_base_offset_read(struct file *file,
return 0; /* the end */
len = snprintf(buf, sizeof(buf), "0x%02zx %zx\n", dbg->off, dbg->cnt);
- if (len < 0)
+ if (len < 0 || len >= sizeof(buf))
return 0;
- if (copy_to_user(buff, buf, len))
+ if ((count < sizeof(buf)) || copy_to_user(buff, buf, len))
return -EFAULT;
*ppos += len; /* increase offset */
@@ -231,10 +231,11 @@ static ssize_t panel_debug_base_reg_read(struct file *file,
if (mdata->debug_inf.debug_enable_clock)
mdata->debug_inf.debug_enable_clock(0);
- if (len < 0)
+ if (len < 0 || len >= sizeof(to_user_buf))
return 0;
- if (copy_to_user(user_buf, to_user_buf, len))
+ if ((count < sizeof(to_user_buf))
+ || copy_to_user(user_buf, to_user_buf, len))
return -EFAULT;
*ppos += len; /* increase offset */
@@ -368,7 +369,7 @@ static ssize_t mdss_debug_base_offset_read(struct file *file,
{
struct mdss_debug_base *dbg = file->private_data;
int len = 0;
- char buf[24];
+ char buf[24] = {'\0'};
if (!dbg)
return -ENODEV;
@@ -377,10 +378,10 @@ static ssize_t mdss_debug_base_offset_read(struct file *file,
return 0; /* the end */
len = snprintf(buf, sizeof(buf), "0x%08zx %zx\n", dbg->off, dbg->cnt);
- if (len < 0)
+ if (len < 0 || len >= sizeof(buf))
return 0;
- if (copy_to_user(buff, buf, len))
+ if ((count < sizeof(buf)) || copy_to_user(buff, buf, len))
return -EFAULT;
*ppos += len; /* increase offset */
@@ -702,7 +703,7 @@ static ssize_t mdss_debug_factor_read(struct file *file,
{
struct mdss_fudge_factor *factor = file->private_data;
int len = 0;
- char buf[32];
+ char buf[32] = {'\0'};
if (!factor)
return -ENODEV;
@@ -712,10 +713,10 @@ static ssize_t mdss_debug_factor_read(struct file *file,
len = snprintf(buf, sizeof(buf), "%d/%d\n",
factor->numer, factor->denom);
- if (len < 0)
+ if (len < 0 || len >= sizeof(buf))
return 0;
- if (copy_to_user(buff, buf, len))
+ if ((count < sizeof(buf)) || copy_to_user(buff, buf, len))
return -EFAULT;
*ppos += len; /* increase offset */
@@ -746,6 +747,8 @@ static ssize_t mdss_debug_perf_mode_write(struct file *file,
if (copy_from_user(buf, user_buf, count))
return -EFAULT;
+ buf[count] = 0; /* end of string */
+
if (sscanf(buf, "%d", &perf_mode) != 1)
return -EFAULT;
@@ -766,7 +769,7 @@ static ssize_t mdss_debug_perf_mode_read(struct file *file,
{
struct mdss_perf_tune *perf_tune = file->private_data;
int len = 0;
- char buf[40];
+ char buf[40] = {'\0'};
if (!perf_tune)
return -ENODEV;
@@ -774,14 +777,12 @@ static ssize_t mdss_debug_perf_mode_read(struct file *file,
if (*ppos)
return 0; /* the end */
- buf[count] = 0;
-
len = snprintf(buf, sizeof(buf), "min_mdp_clk %lu min_bus_vote %llu\n",
perf_tune->min_mdp_clk, perf_tune->min_bus_vote);
- if (len < 0)
+ if (len < 0 || len >= sizeof(buf))
return 0;
- if (copy_to_user(buff, buf, len))
+ if ((count < sizeof(buf)) || copy_to_user(buff, buf, len))
return -EFAULT;
*ppos += len; /* increase offset */
@@ -801,7 +802,7 @@ static ssize_t mdss_debug_perf_panic_read(struct file *file,
{
struct mdss_data_type *mdata = file->private_data;
int len = 0;
- char buf[40];
+ char buf[40] = {'\0'};
if (!mdata)
return -ENODEV;
@@ -811,10 +812,10 @@ static ssize_t mdss_debug_perf_panic_read(struct file *file,
len = snprintf(buf, sizeof(buf), "%d\n",
!mdata->has_panic_ctrl);
- if (len < 0)
+ if (len < 0 || len >= sizeof(buf))
return 0;
- if (copy_to_user(buff, buf, len))
+ if ((count < sizeof(buf)) || copy_to_user(buff, buf, len))
return -EFAULT;
*ppos += len; /* increase offset */
@@ -877,9 +878,14 @@ static ssize_t mdss_debug_perf_panic_write(struct file *file,
if (!mdata)
return -EFAULT;
+ if (count >= sizeof(buf))
+ return -EFAULT;
+
if (copy_from_user(buf, user_buf, count))
return -EFAULT;
+ buf[count] = 0; /* end of string */
+
if (sscanf(buf, "%d", &disable_panic) != 1)
return -EFAULT;
--
1.8.2.1