From 600ecb6934ac2c48fe9db7af318ba94a9d5ea599 Mon Sep 17 00:00:00 2001 From: Ke Ai Date: Fri, 15 Jun 2012 19:19:14 +0800 Subject: [PATCH] GFX-Display: fix mistake in /proc/display_status. BZ: 42140 system will hange ,when using /proc/display_status. it is related to buf overflow ,which been not protected well. one example: echo "a b000 b100">/proc/display_status cat /proc/display_status Change-Id: I4695e6b8a9a31faaee6e437bbd0ae3e5d5b7900f Signed-off-by: Ke Ai Reviewed-on: http://android.intel.com:8080/53129 Reviewed-by: Xu, Randy Tested-by: Tong, BoX Reviewed-by: buildbot Tested-by: buildbot --- drivers/staging/mrst/drv/psb_drv.c | 44 ++++++++++++++++++++++++++------------ drivers/staging/mrst/drv/psb_drv.h | 4 +++- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/drivers/staging/mrst/drv/psb_drv.c b/drivers/staging/mrst/drv/psb_drv.c index 1937dc2..882382c 100644 --- a/drivers/staging/mrst/drv/psb_drv.c +++ b/drivers/staging/mrst/drv/psb_drv.c @@ -1776,6 +1776,10 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset) dev_priv->bhdmiconnected = false; dev_priv->dpms_on_off = false; dev_priv->brightness_adjusted = 0; + dev_priv->buf = kzalloc(PSB_REG_PRINT_SIZE * sizeof(char), + GFP_KERNEL); + if (dev_priv->buf == NULL) + return -ENOMEM; #ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE dev_priv->hdmi_audio_busy = 0; @@ -3864,7 +3868,8 @@ static int psb_display_register_read(char *buf, char **start, off_t offset, int /*do nothing*/ int len = dev_priv->count; *eof = 1; - memcpy(buf, dev_priv->buf, dev_priv->count); + if (dev_priv->buf && dev_priv->count < PSB_REG_PRINT_SIZE) + memcpy(buf, dev_priv->buf, dev_priv->count); return len - offset; } /* @@ -3887,6 +3892,7 @@ static int psb_display_register_write(struct file *file, const char *buffer, unsigned int val = 0; int len = 0; int Offset = 0; + int add_size = 0; dev_priv->count = 0; memset(buf, '\0', sizeof(buf)); @@ -3933,18 +3939,18 @@ static int psb_display_register_write(struct file *file, const char *buffer, } if (is_panel_vid_or_cmd(dev) == MDFLD_DSI_ENCODER_DBI) { #ifndef CONFIG_MDFLD_DSI_DPU - if (!(dev_priv->dsr_fb_update & MDFLD_DSR_MIPI_CONTROL) && - (dev_priv->dbi_panel_on || dev_priv->dbi_panel_on2)) - mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_MIPI_CONTROL, 0, 0); //assume cursor move once - - dsr_info = dev_priv->dbi_dsr_info; - dbi_outputs = dsr_info->dbi_outputs; - dbi_output = dbi_outputs[0]; - /*make sure, during read no DSR again*/ - dbi_output->mode_flags |= MODE_SETTING_ON_GOING; + if (dev_priv->b_dsr_enable) { + dev_priv->exit_idle(dev, + MDFLD_DSR_2D_3D, + NULL, + true); + dsr_info = dev_priv->dbi_dsr_info; + dbi_outputs = dsr_info->dbi_outputs; + dbi_output = dbi_outputs[0]; + /*make sure, during read no DSR again*/ + dbi_output->mode_flags |= MODE_SETTING_ON_GOING; + } #endif - PSB_WVDC32(0x30164, PSB_RVDC32(0x30164) | BIT16); - printk(KERN_ALERT "Overlay0x30164 0x%x\n", PSB_RVDC32(0x30164)); } if (op == 'r') { if (reg >= 0xa000) { @@ -3954,6 +3960,9 @@ static int psb_display_register_write(struct file *file, const char *buffer, reg_val = SGX_REG_READ(reg); PSB_DEBUG_ENTRY("SGX Read :reg=0x%08x , val=0x%08x.\n", reg, reg_val); } + add_size = sizeof("0xFFFFFFFF 0xFFFFFFFF\n"); + if (dev_priv->buf && + (dev_priv->count + add_size) < PSB_REG_PRINT_SIZE) dev_priv->count = sprintf(dev_priv->buf, "%08x %08x\n", reg, reg_val); } if (op == 'w') { @@ -4011,6 +4020,9 @@ static int psb_display_register_write(struct file *file, const char *buffer, REG_READ(Offset + 0x8), REG_READ(Offset + 0xc)); + add_size = 5 * sizeof("0xFFFFFFFF "); + if (dev_priv->buf && + (dev_priv->count + add_size) < PSB_REG_PRINT_SIZE) dev_priv->count += sprintf(dev_priv->buf + dev_priv->count, "%08x %08x %08x %08x %08x\n", Offset, @@ -4026,7 +4038,10 @@ static int psb_display_register_write(struct file *file, const char *buffer, SGX_REG_READ(Offset + 0x8), SGX_REG_READ(Offset + 0xc)); - dev_priv->count += sprintf(dev_priv->buf + dev_priv->count, + add_size = 5 * sizeof("0xFFFFFFFF "); + if (dev_priv->buf && + (dev_priv->count + add_size) < PSB_REG_PRINT_SIZE) + dev_priv->count += sprintf(dev_priv->buf + dev_priv->count, "%08x %08x %08x %08x %08x\n", Offset, SGX_REG_READ(Offset + 0x0), @@ -4039,7 +4054,8 @@ static int psb_display_register_write(struct file *file, const char *buffer, } if (is_panel_vid_or_cmd(dev) == MDFLD_DSI_ENCODER_DBI) { #ifndef CONFIG_MDFLD_DSI_DPU - dbi_output->mode_flags &= ~MODE_SETTING_ON_GOING; + if (dev_priv->b_dsr_enable) + dbi_output->mode_flags &= ~MODE_SETTING_ON_GOING; #endif } ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); diff --git a/drivers/staging/mrst/drv/psb_drv.h b/drivers/staging/mrst/drv/psb_drv.h index 24d79ab..d81b263 100644 --- a/drivers/staging/mrst/drv/psb_drv.h +++ b/drivers/staging/mrst/drv/psb_drv.h @@ -433,6 +433,8 @@ typedef int(* pfn_screen_event_handler)(struct drm_device* psDrmDevice, int stat #define GCT_R10_HEADER_SIZE 16 #define GCT_R10_DISPLAY_DESC_SIZE 28 +#define PSB_REG_PRINT_SIZE 40960 + struct drm_psb_private { /* * DSI info. @@ -1079,7 +1081,7 @@ struct drm_psb_private { /* read register value through sysfs. */ int count; - char buf[256]; + char *buf; /*for HDMI flip chain*/ #define DRM_PSB_HDMI_FLIP_ARRAY_SIZE 4 -- 2.7.4