From 1d718286c4c482502a2c4356cebef28aef2fb01f Mon Sep 17 00:00:00 2001 From: Rahul Sharma Date: Wed, 28 Jun 2017 15:46:19 +0530 Subject: msm: vfe : Fix for multiple buffer over read/write Implemented validation of user space values in ioctl call before processing buffers in response to user commands. Change-Id: Icf6e49650bab358b764ebf1db24925a4063c5842 Signed-off-by: Rahul Sharma --- drivers/media/video/msm/vfe/msm_vfe32.c | 246 ++++++++++++++++++++++++++++++++ 1 file changed, 246 insertions(+) diff --git a/drivers/media/video/msm/vfe/msm_vfe32.c b/drivers/media/video/msm/vfe/msm_vfe32.c index 64f3e7b..1509a04 100644 --- a/drivers/media/video/msm/vfe/msm_vfe32.c +++ b/drivers/media/video/msm/vfe/msm_vfe32.c @@ -2275,6 +2275,7 @@ static int vfe32_proc_general( uint32_t *cmdp_local = NULL; uint32_t snapshot_cnt = 0; uint32_t temp1 = 0, temp2 = 0; + uint32_t maxvalue = 0; struct msm_camera_vfe_params_t vfe_params; switch (cmd->id) { @@ -2373,6 +2374,14 @@ static int vfe32_proc_general( __func__); goto proc_general_done; } + if (cmd->id < 0 || cmd->id >= ARRAY_SIZE(vfe32_cmd)) { + rc = -EINVAL; + goto proc_general_done; + } + if (cmd->length < vfe32_cmd[cmd->id].length) { + rc = -EINVAL; + goto proc_general_done; + } cmdp = kmalloc(cmd->length, GFP_ATOMIC); if (!cmdp) { rc = -ENOMEM; @@ -2407,6 +2416,14 @@ static int vfe32_proc_general( __func__); goto proc_general_done; } + if (cmd->id < 0 || cmd->id >= ARRAY_SIZE(vfe32_cmd)) { + rc = -EINVAL; + goto proc_general_done; + } + if (cmd->length < vfe32_cmd[cmd->id].length) { + rc = -EINVAL; + goto proc_general_done; + } cmdp = kmalloc(cmd->length, GFP_ATOMIC); if (!cmdp) { rc = -ENOMEM; @@ -2441,6 +2458,14 @@ static int vfe32_proc_general( __func__); goto proc_general_done; } + if (cmd->id < 0 || cmd->id >= ARRAY_SIZE(vfe32_cmd)) { + rc = -EINVAL; + goto proc_general_done; + } + if (cmd->length < vfe32_cmd[cmd->id].length) { + rc = -EINVAL; + goto proc_general_done; + } cmdp = kmalloc(cmd->length, GFP_ATOMIC); if (!cmdp) { rc = -ENOMEM; @@ -2471,6 +2496,14 @@ static int vfe32_proc_general( __func__); goto proc_general_done; } + if (cmd->id < 0 || cmd->id >= ARRAY_SIZE(vfe32_cmd)) { + rc = -EINVAL; + goto proc_general_done; + } + if (cmd->length < vfe32_cmd[cmd->id].length) { + rc = -EINVAL; + goto proc_general_done; + } cmdp = kmalloc(cmd->length, GFP_ATOMIC); if (!cmdp) { rc = -ENOMEM; @@ -2502,6 +2535,14 @@ static int vfe32_proc_general( __func__); goto proc_general_done; } + if (cmd->id < 0 || cmd->id >= ARRAY_SIZE(vfe32_cmd)) { + rc = -EINVAL; + goto proc_general_done; + } + if (cmd->length < vfe32_cmd[cmd->id].length) { + rc = -EINVAL; + goto proc_general_done; + } cmdp = kmalloc(cmd->length, GFP_ATOMIC); if (!cmdp) { rc = -ENOMEM; @@ -2527,6 +2568,14 @@ static int vfe32_proc_general( __func__); goto proc_general_done; } + if (cmd->id < 0 || cmd->id >= ARRAY_SIZE(vfe32_cmd)) { + rc = -EINVAL; + goto proc_general_done; + } + if (cmd->length < vfe32_cmd[cmd->id].length) { + rc = -EINVAL; + goto proc_general_done; + } cmdp = kmalloc(cmd->length, GFP_ATOMIC); if (!cmdp) { rc = -ENOMEM; @@ -2589,6 +2638,14 @@ static int vfe32_proc_general( VFE_STATS_CFG); msm_camera_io_w(module_val, vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG); + if (cmd->id < 0 || cmd->id >= ARRAY_SIZE(vfe32_cmd)) { + rc = -EINVAL; + goto proc_general_done; + } + if (cmd->length < vfe32_cmd[cmd->id].length) { + rc = -EINVAL; + goto proc_general_done; + } cmdp = kmalloc(cmd->length, GFP_ATOMIC); if (!cmdp) { rc = -ENOMEM; @@ -2627,6 +2684,10 @@ static int vfe32_proc_general( new_val = *cmdp_local; old_val &= MCE_EN_MASK; new_val = new_val | old_val; + if (cmd->length < 4) { + rc = -EINVAL; + goto proc_general_done; + } msm_camera_io_memcpy( vfe32_ctrl->share_ctrl->vfebase + V32_CHROMA_SUP_OFF + 4, &new_val, 4); @@ -2637,10 +2698,23 @@ static int vfe32_proc_general( new_val = *cmdp_local; old_val &= MCE_Q_K_MASK; new_val = new_val | old_val; + if (cmd->length < (4 + sizeof(uint32_t)*1)) { + rc = -EINVAL; + goto proc_general_done; + } msm_camera_io_memcpy( vfe32_ctrl->share_ctrl->vfebase + V32_CHROMA_SUP_OFF + 8, &new_val, 4); cmdp_local += 1; + if (cmd->id < 0 || cmd->id >= ARRAY_SIZE(vfe32_cmd)) { + rc = -EINVAL; + goto proc_general_done; + } + if (cmd->length < (vfe32_cmd[cmd->id].length + + sizeof(uint32_t) * (1 + 1))) { + rc = -EINVAL; + goto proc_general_done; + } msm_camera_io_memcpy( vfe32_ctrl->share_ctrl->vfebase + vfe32_cmd[cmd->id].offset, @@ -2661,6 +2735,10 @@ static int vfe32_proc_general( goto proc_general_done; } cmdp_local = cmdp; + if (cmd->length < 4) { + rc = -EINVAL; + goto proc_general_done; + } msm_camera_io_memcpy(vfe32_ctrl->share_ctrl->vfebase + V32_CHROMA_SUP_OFF, cmdp_local, 4); @@ -2673,6 +2751,11 @@ static int vfe32_proc_general( V32_CHROMA_SUP_OFF + 4); old_val &= ~MCE_EN_MASK; new_val = new_val | old_val; + /* As cmdp_local got incremented by 1*/ + if (cmd->length < (4 + sizeof(uint32_t) * 1)) { + rc = -EINVAL; + goto proc_general_done; + } msm_camera_io_memcpy( vfe32_ctrl->share_ctrl->vfebase + V32_CHROMA_SUP_OFF + 4, &new_val, 4); @@ -2683,6 +2766,10 @@ static int vfe32_proc_general( new_val = *cmdp_local; old_val &= ~MCE_Q_K_MASK; new_val = new_val | old_val; + if (cmd->length < (4 + sizeof(uint32_t) * (1 + 1))) { + rc = -EINVAL; + goto proc_general_done; + } msm_camera_io_memcpy( vfe32_ctrl->share_ctrl->vfebase + V32_CHROMA_SUP_OFF + 8, &new_val, 4); @@ -2704,12 +2791,22 @@ static int vfe32_proc_general( goto proc_general_done; } cmdp_local = cmdp; + if (cmd->length < 16) { + rc = -EINVAL; + goto proc_general_done; + } msm_camera_io_memcpy( vfe32_ctrl->share_ctrl->vfebase + vfe32_cmd[cmd->id].offset, cmdp_local, 16); cmdp_local += 4; vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK0, vfe32_ctrl); + if (cmd->length < (sizeof(uint32_t) * + (4 + V32_MESH_ROLL_OFF_INIT_TABLE_SIZE * 2 + + V32_MESH_ROLL_OFF_DELTA_TABLE_SIZE * 2))) { + rc = -EINVAL; + goto proc_general_done; + } /* for loop for extrcting init table. */ for (i = 0; i < (V32_MESH_ROLL_OFF_INIT_TABLE_SIZE * 2); i++) { msm_camera_io_w(*cmdp_local , @@ -2773,6 +2870,14 @@ static int vfe32_proc_general( } break; case VFE_CMD_LA_CFG: + if (cmd->id < 0 || cmd->id >= ARRAY_SIZE(vfe32_cmd)) { + rc = -EINVAL; + goto proc_general_done; + } + if (cmd->length < vfe32_cmd[cmd->id].length) { + rc = -EINVAL; + goto proc_general_done; + } cmdp = kmalloc(cmd->length, GFP_ATOMIC); if (!cmdp) { rc = -ENOMEM; @@ -2813,6 +2918,11 @@ static int vfe32_proc_general( cmdp_local = cmdp + 1; old_val = msm_camera_io_r( vfe32_ctrl->share_ctrl->vfebase + V32_LA_OFF); + if (cmd->length < (sizeof(uint32_t) * (1 + + (VFE32_LA_TABLE_LENGTH / 2)))) { + rc = -EINVAL; + goto proc_general_done; + } if (old_val != 0x0) vfe32_write_la_cfg(LUMA_ADAPT_LUT_RAM_BANK0, cmdp_local, vfe32_ctrl); @@ -2861,6 +2971,10 @@ static int vfe32_proc_general( break; case VFE_CMD_SK_ENHAN_CFG: case VFE_CMD_SK_ENHAN_UPDATE:{ + if (cmd->length < V32_SCE_LEN) { + rc = -EINVAL; + goto proc_general_done; + } cmdp = kmalloc(cmd->length, GFP_ATOMIC); if (!cmdp) { rc = -ENOMEM; @@ -2895,17 +3009,31 @@ static int vfe32_proc_general( goto proc_general_done; } cmdp_local = cmdp; + if (cmd->length < V32_LINEARIZATION_LEN1) { + rc = -EINVAL; + goto proc_general_done; + } msm_camera_io_memcpy( vfe32_ctrl->share_ctrl->vfebase + V32_LINEARIZATION_OFF1, cmdp_local, V32_LINEARIZATION_LEN1); cmdp_local += 4; + if (cmd->length < (V32_LINEARIZATION_LEN2 + + sizeof(uint32_t) * 4)) { + rc = -EINVAL; + goto proc_general_done; + } msm_camera_io_memcpy( vfe32_ctrl->share_ctrl->vfebase + V32_LINEARIZATION_OFF2, cmdp_local, V32_LINEARIZATION_LEN2); cmdp_local = cmdp + 17; + if (cmd->length < (sizeof(uint32_t) * + (VFE32_LINEARIZATON_TABLE_LENGTH + 17))) { + rc = -EINVAL; + goto proc_general_done; + } vfe32_write_linear_cfg(BLACK_LUT_RAM_BANK0, cmdp_local, vfe32_ctrl); break; @@ -2923,11 +3051,20 @@ static int vfe32_proc_general( } cmdp_local = cmdp; cmdp_local++; + if (cmd->length < V32_LINEARIZATION_LEN1) { + rc = -EINVAL; + goto proc_general_done; + } msm_camera_io_memcpy( vfe32_ctrl->share_ctrl->vfebase + V32_LINEARIZATION_OFF1 + 4, cmdp_local, (V32_LINEARIZATION_LEN1 - 4)); cmdp_local += 3; + if (cmd->length < (V32_LINEARIZATION_LEN2 + + sizeof(uint32_t) * (1 + 3))) { + rc = -EINVAL; + goto proc_general_done; + } msm_camera_io_memcpy( vfe32_ctrl->share_ctrl->vfebase + V32_LINEARIZATION_OFF2, @@ -2938,6 +3075,11 @@ static int vfe32_proc_general( vfe32_ctrl->share_ctrl->vfebase + V32_LINEARIZATION_OFF1); + if (cmd->length < (sizeof(uint32_t) * + (VFE32_LINEARIZATON_TABLE_LENGTH + 17))) { + rc = -EINVAL; + goto proc_general_done; + } if (old_val != 0x0) vfe32_write_linear_cfg(BLACK_LUT_RAM_BANK0, cmdp_local, vfe32_ctrl); @@ -3084,11 +3226,24 @@ static int vfe32_proc_general( new_val = new_val | old_val; *cmdp_local = new_val; + if (cmd->length < 4) { + rc = -EINVAL; + goto proc_general_done; + } msm_camera_io_memcpy( vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_0_OFF, cmdp_local, 4); cmdp_local += 1; + if (cmd->id < 0 || cmd->id >= ARRAY_SIZE(vfe32_cmd)) { + rc = -EINVAL; + goto proc_general_done; + } + if (cmd->length < (vfe32_cmd[cmd->id].length + + sizeof(uint32_t) * 1)) { + rc = -EINVAL; + goto proc_general_done; + } msm_camera_io_memcpy( vfe32_ctrl->share_ctrl->vfebase + vfe32_cmd[cmd->id].offset, @@ -3118,10 +3273,23 @@ static int vfe32_proc_general( new_val = new_val | old_val; *cmdp_local = new_val; + if (cmd->length < 4) { + rc = -EINVAL; + goto proc_general_done; + } msm_camera_io_memcpy( vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_0_OFF, cmdp_local, 4); cmdp_local += 1; + if (cmd->id < 0 || cmd->id >= ARRAY_SIZE(vfe32_cmd)) { + rc = -EINVAL; + goto proc_general_done; + } + if (cmd->length < (vfe32_cmd[cmd->id].length + + sizeof(uint32_t) * 1)) { + rc = -EINVAL; + goto proc_general_done; + } msm_camera_io_memcpy( vfe32_ctrl->share_ctrl->vfebase + vfe32_cmd[cmd->id].offset, @@ -3150,9 +3318,18 @@ static int vfe32_proc_general( new_val = new_val | old_val; *cmdp_local = new_val; + if (cmd->length < V32_DEMOSAICV3_LEN) { + rc = -EINVAL; + goto proc_general_done; + } msm_camera_io_memcpy(vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_0_OFF, cmdp_local, V32_DEMOSAICV3_LEN); + if (cmd->length < (V32_DEMOSAICV3_DBPC_LEN + + sizeof(uint32_t) * 4)) { + rc = -EINVAL; + goto proc_general_done; + } cmdp_local += 1; msm_camera_io_memcpy(vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_DBPC_CFG_OFF, @@ -3183,6 +3360,11 @@ static int vfe32_proc_general( rc = -EFAULT; goto proc_general_done; } + if (cmd->length < (sizeof(uint32_t) * (1 + + VFE32_GAMMA_NUM_ENTRIES / 2))) { + rc = -EINVAL; + goto proc_general_done; + } msm_camera_io_memcpy( vfe32_ctrl->share_ctrl->vfebase + V32_RGB_G_OFF, cmdp, 4); @@ -3207,6 +3389,16 @@ static int vfe32_proc_general( rc = -EFAULT; goto proc_general_done; } + maxvalue = (VFE32_GAMMA_CH0_G_POS > VFE32_GAMMA_CH1_B_POS) ? + VFE32_GAMMA_CH0_G_POS : VFE32_GAMMA_CH1_B_POS; + maxvalue = (maxvalue > VFE32_GAMMA_CH2_R_POS) ? + maxvalue : VFE32_GAMMA_CH2_R_POS; + + if (cmd->length < (sizeof(uint32_t) * (1 + + maxvalue + (VFE32_GAMMA_NUM_ENTRIES / 2)))) { + rc = -EINVAL; + goto proc_general_done; + } msm_camera_io_memcpy( vfe32_ctrl->share_ctrl->vfebase + V32_RGB_G_OFF, cmdp, 4); @@ -3236,6 +3428,17 @@ static int vfe32_proc_general( old_val = msm_camera_io_r( vfe32_ctrl->share_ctrl->vfebase + V32_RGB_G_OFF); cmdp += 1; + + maxvalue = (VFE32_GAMMA_CH0_G_POS > VFE32_GAMMA_CH1_B_POS) ? + VFE32_GAMMA_CH0_G_POS : VFE32_GAMMA_CH1_B_POS; + maxvalue = (maxvalue > VFE32_GAMMA_CH2_R_POS) ? + maxvalue : VFE32_GAMMA_CH2_R_POS; + + if (cmd->length < (sizeof(uint32_t) * (1 + + maxvalue + (VFE32_GAMMA_NUM_ENTRIES / 2)))) { + rc = -EINVAL; + goto proc_general_done; + } if (old_val != 0x0) { vfe32_write_gamma_cfg(RGBLUT_RAM_CH0_BANK0, cmdp + VFE32_GAMMA_CH0_G_POS, vfe32_ctrl); @@ -3271,6 +3474,11 @@ static int vfe32_proc_general( old_val = msm_camera_io_r( vfe32_ctrl->share_ctrl->vfebase + V32_RGB_G_OFF); cmdp += 1; + if (cmd->length < (sizeof(uint32_t) * (1 + ( + VFE32_GAMMA_NUM_ENTRIES / 2)))) { + rc = -EINVAL; + goto proc_general_done; + } if (old_val != 0x0) { vfe32_write_gamma_cfg( RGBLUT_RAM_CH0_BANK0, cmdp, vfe32_ctrl); @@ -3442,10 +3650,24 @@ static int vfe32_proc_general( rc = -EFAULT; goto proc_general_done; } + /* As cmdp gets incremented 7 times in function + vfe32_sync_timer_start() */ + if (cmd->length < (sizeof(uint32_t) * 7)) { + rc = -EINVAL; + goto proc_general_done; + } vfe32_sync_timer_start(cmdp, vfe32_ctrl); break; case VFE_CMD_MODULE_CFG: { + if (cmd->id < 0 || cmd->id >= ARRAY_SIZE(vfe32_cmd)) { + rc = -EINVAL; + goto proc_general_done; + } + if (cmd->length < vfe32_cmd[cmd->id].length) { + rc = -EINVAL; + goto proc_general_done; + } cmdp = kmalloc(cmd->length, GFP_ATOMIC); if (!cmdp) { rc = -ENOMEM; @@ -3496,11 +3718,24 @@ static int vfe32_proc_general( rc = -EFAULT; goto proc_general_done; } + if (cmd->id < 0 || cmd->id >= ARRAY_SIZE(vfe32_cmd)) { + rc = -EINVAL; + goto proc_general_done; + } + if (cmd->length < vfe32_cmd[cmd->id].length) { + rc = -EINVAL; + goto proc_general_done; + } msm_camera_io_memcpy( vfe32_ctrl->share_ctrl->vfebase + vfe32_cmd[cmd->id].offset, cmdp, (vfe32_cmd[cmd->id].length)); cmdp_local = cmdp + V32_ASF_LEN/4; + if (cmd->length < (sizeof(uint32_t) * (V32_ASF_LEN / 4) + + V32_ASF_SPECIAL_EFX_CFG_LEN)) { + rc = -EINVAL; + goto proc_general_done; + } msm_camera_io_memcpy( vfe32_ctrl->share_ctrl->vfebase + V32_ASF_SPECIAL_EFX_CFG_OFF, @@ -3508,6 +3743,12 @@ static int vfe32_proc_general( break; case VFE_CMD_PCA_ROLL_OFF_CFG: + + if (cmd->length < (sizeof(uint32_t) * (8 + 4 * + V33_PCA_ROLL_OFF_TABLE_SIZE))) { + rc = -EINVAL; + goto proc_general_done; + } cmdp = kmalloc(cmd->length, GFP_ATOMIC); if (!cmdp) { rc = -ENOMEM; @@ -3566,6 +3807,11 @@ static int vfe32_proc_general( break; case VFE_CMD_PCA_ROLL_OFF_UPDATE: + if (cmd->length < (sizeof(uint32_t) * (8 + 4 * + V33_PCA_ROLL_OFF_TABLE_SIZE))) { + rc = -EINVAL; + goto proc_general_done; + } cmdp = kmalloc(cmd->length, GFP_ATOMIC); if (!cmdp) { rc = -ENOMEM; -- cgit v1.1