From bb760cae598c741d8eeb4a5543ef296804b3aa44 Mon Sep 17 00:00:00 2001 From: "Sravan Kumar D.V.N" Date: Wed, 5 Jul 2017 11:49:28 +0530 Subject: [PATCH 1/2] msm: mdss: Fix possible leaks in PP LUT get functions Possible user information leaks in post processing LUT get functions are fixed by properly copying user data. Change-Id: I529f74a79e5857902177c8054d136b4544370be2 Signed-off-by: Sravan Kumar D.V.N --- drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c | 20 +++++++++++++++----- drivers/video/fbdev/msm/mdss_mdp_pp_v3.c | 11 ++++++++--- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c b/drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c index 71cab148e1c3..9ef6a6634b78 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-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 @@ -358,7 +358,8 @@ static int pp_hist_lut_get_config(char __iomem *base_addr, void *cfg_data, int ret = 0, i = 0; char __iomem *hist_addr; u32 sz = 0, temp = 0, *data = NULL; - struct mdp_hist_lut_data_v1_7 *lut_data = NULL; + struct mdp_hist_lut_data_v1_7 lut_data_v1_7; + struct mdp_hist_lut_data_v1_7 *lut_data = &lut_data_v1_7; struct mdp_hist_lut_data *lut_cfg_data = NULL; if (!base_addr || !cfg_data) { @@ -378,7 +379,11 @@ static int pp_hist_lut_get_config(char __iomem *base_addr, void *cfg_data, lut_cfg_data->version, lut_cfg_data->cfg_payload); return -EINVAL; } - lut_data = lut_cfg_data->cfg_payload; + if (copy_from_user(lut_data, (void __user *) lut_cfg_data->cfg_payload, + sizeof(*lut_data))) { + pr_err("copy from user failed for lut_data\n"); + return -EFAULT; + } if (lut_data->len != ENHIST_LUT_ENTRIES) { pr_err("invalid hist_lut len %d", lut_data->len); return -EINVAL; @@ -1786,7 +1791,8 @@ static int pp_igc_get_config(char __iomem *base_addr, void *cfg_data, { int ret = 0, i = 0; struct mdp_igc_lut_data *lut_cfg_data = NULL; - struct mdp_igc_lut_data_v1_7 *lut_data = NULL; + struct mdp_igc_lut_data_v1_7 lut_data_v1_7; + struct mdp_igc_lut_data_v1_7 *lut_data = &lut_data_v1_7; char __iomem *c1 = NULL, *c2 = NULL; u32 *c0c1_data = NULL, *c2_data = NULL; u32 data = 0, sz = 0; @@ -1810,7 +1816,11 @@ static int pp_igc_get_config(char __iomem *base_addr, void *cfg_data, ret = -EINVAL; goto exit; } - lut_data = lut_cfg_data->cfg_payload; + if (copy_from_user(lut_data, (void __user *) lut_cfg_data->cfg_payload, + sizeof(*lut_data))) { + pr_err("copy from user failed for lut_data\n"); + return -EFAULT; + } if (lut_data->len != IGC_LUT_ENTRIES) { pr_err("invalid lut len %d\n", lut_data->len); ret = -EINVAL; diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp_v3.c b/drivers/video/fbdev/msm/mdss_mdp_pp_v3.c index 25cb94f89dd5..b377f0921508 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pp_v3.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pp_v3.c @@ -1,5 +1,5 @@ /* - * 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 @@ -298,7 +298,8 @@ static int pp_hist_lut_get_config(char __iomem *base_addr, void *cfg_data, int ret = 0, i = 0; char __iomem *hist_lut_addr; u32 sz = 0, temp = 0, *data = NULL; - struct mdp_hist_lut_data_v1_7 *lut_data = NULL; + struct mdp_hist_lut_data_v1_7 lut_data_v1_7; + struct mdp_hist_lut_data_v1_7 *lut_data = &lut_data_v1_7; struct mdp_hist_lut_data *lut_cfg_data = NULL; if (!base_addr || !cfg_data) { @@ -323,7 +324,11 @@ static int pp_hist_lut_get_config(char __iomem *base_addr, void *cfg_data, lut_cfg_data->version, lut_cfg_data->cfg_payload); return -EINVAL; } - lut_data = lut_cfg_data->cfg_payload; + if (copy_from_user(lut_data, (void __user *) lut_cfg_data->cfg_payload, + sizeof(*lut_data))) { + pr_err("copy from user failed for lut_data\n"); + return -EFAULT; + } if (lut_data->len != ENHIST_LUT_ENTRIES) { pr_err("invalid hist_lut len %d", lut_data->len); return -EINVAL; From 99a3334a220079b36667f27019f8feca944c96ea Mon Sep 17 00:00:00 2001 From: "Sravan Kumar D.V.N" Date: Wed, 5 Jul 2017 11:59:08 +0530 Subject: [PATCH 2/2] msm: mdss: Fix possible memory overwrite in pgc config Possible memory overwrite in pgc get config is fixed by eliminating direct reference to user data. Change-Id: I7117848bacb8e69720eb3121d02bbacf02cab13a Signed-off-by: Sravan Kumar D.V.N --- drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c b/drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c index 9ef6a6634b78..aabf7c507376 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pp_v1_7.c @@ -1964,20 +1964,24 @@ static int pp_pgc_get_config(char __iomem *base_addr, void *cfg_data, u32 *c0_data = NULL, *c1_data = NULL, *c2_data = NULL; u32 val = 0, i = 0, sz = 0; struct mdp_pgc_lut_data *pgc_data = NULL; - struct mdp_pgc_lut_data_v1_7 *pgc_data_v17 = NULL; + struct mdp_pgc_lut_data_v1_7 pgc_lut_data_v17; + struct mdp_pgc_lut_data_v1_7 *pgc_data_v17 = &pgc_lut_data_v17; if (!base_addr || !cfg_data) { pr_err("invalid params base_addr %pK cfg_data %pK block_type %d\n", base_addr, cfg_data, block_type); return -EINVAL; } pgc_data = (struct mdp_pgc_lut_data *) cfg_data; - pgc_data_v17 = (struct mdp_pgc_lut_data_v1_7 *) - pgc_data->cfg_payload; - if (pgc_data->version != mdp_pgc_v1_7 || !pgc_data_v17) { + if (pgc_data->version != mdp_pgc_v1_7 || !pgc_data->cfg_payload) { pr_err("invalid pgc version %d payload %pK\n", - pgc_data->version, pgc_data_v17); + pgc_data->version, pgc_data->cfg_payload); return -EINVAL; } + if (copy_from_user(pgc_data_v17, (void __user *) pgc_data->cfg_payload, + sizeof(*pgc_data_v17))) { + pr_err("copy from user failed for pgc lut data\n"); + return -EFAULT; + } if (!(pgc_data->flags & MDP_PP_OPS_READ)) { pr_info("read ops is not set %d", pgc_data->flags); return -EINVAL;