From c6d874fd2c515406bc33ab78d60df70a47bddae2 Mon Sep 17 00:00:00 2001 From: Andrew Chant Date: Fri, 7 Apr 2017 10:42:31 -0700 Subject: [PATCH] input: synaptics_dsx: valid bounds of intr_reg_num Validate the intr_reg_num value returned by touchscreen to ensure no out of bounds access can occur. Bug: 35472278 Change-Id: If98e7091bf938061ac1b473ec652a620f118dbf0 Signed-off-by: Andrew Chant --- .../synaptics_dsx_htc_2.6/synaptics_dsx_core.c | 50 ++++++++++++++++------ 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_core.c b/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_core.c index 90b6fc37284b7..dbe242808841b 100644 --- a/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_core.c +++ b/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_core.c @@ -2460,14 +2460,20 @@ static int synaptics_rmi4_irq_enable(struct synaptics_rmi4_data *rmi4_data, return retval; } -static void synaptics_rmi4_set_intr_mask(struct synaptics_rmi4_fn *fhandler, - struct synaptics_rmi4_fn_desc *fd, - unsigned int intr_count) +static int synaptics_rmi4_set_intr_mask(struct synaptics_rmi4_fn *fhandler, + struct synaptics_rmi4_fn_desc *fd, + unsigned int intr_count) { unsigned char ii; unsigned char intr_offset; fhandler->intr_reg_num = (intr_count + 7) / 8; + if (fhandler->intr_reg_num >= MAX_INTR_REGISTERS) { + fhandler->intr_reg_num = 0; + fhandler->num_of_data_sources = 0; + fhandler->intr_mask = 0; + return -EINVAL; + } if (fhandler->intr_reg_num != 0) fhandler->intr_reg_num -= 1; @@ -2479,7 +2485,7 @@ static void synaptics_rmi4_set_intr_mask(struct synaptics_rmi4_fn *fhandler, ii++) fhandler->intr_mask |= 1 << ii; - return; + return 0; } static int synaptics_rmi4_f01_init(struct synaptics_rmi4_data *rmi4_data, @@ -2487,12 +2493,16 @@ static int synaptics_rmi4_f01_init(struct synaptics_rmi4_data *rmi4_data, struct synaptics_rmi4_fn_desc *fd, unsigned int intr_count) { + int retval; + fhandler->fn_number = fd->fn_number; fhandler->num_of_data_sources = fd->intr_src_count; fhandler->data = NULL; fhandler->extra = NULL; - synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); + retval = synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); + if (retval < 0) + return retval; rmi4_data->f01_query_base_addr = fd->query_base_addr; rmi4_data->f01_ctrl_base_addr = fd->ctrl_base_addr; @@ -2578,7 +2588,9 @@ static int synaptics_rmi4_f11_init(struct synaptics_rmi4_data *rmi4_data, rmi4_data->sensor_max_y = temp; } - synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); + retval = synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); + if (retval < 0) + return retval; fhandler->data = NULL; @@ -3362,7 +3374,9 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data, return retval; } - synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); + retval = synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); + if (retval < 0) + return retval; /* Allocate memory for finger data storage space */ fhandler->data_size = num_of_fingers * size_of_2d_data; @@ -3569,7 +3583,9 @@ static int synaptics_rmi4_f1a_init(struct synaptics_rmi4_data *rmi4_data, fhandler->fn_number = fd->fn_number; fhandler->num_of_data_sources = fd->intr_src_count; - synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); + retval = synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); + if (retval < 0) + return retval; retval = synaptics_rmi4_f1a_alloc_mem(rmi4_data, fhandler); if (retval < 0) @@ -3596,12 +3612,16 @@ static int synaptics_rmi4_f34_init(struct synaptics_rmi4_data *rmi4_data, unsigned int intr_count, unsigned int page_number) { + int retval; + fhandler->fn_number = fd->fn_number; fhandler->num_of_data_sources = fd->intr_src_count; fhandler->data = NULL; fhandler->extra = NULL; - synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); + retval = synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); + if (retval < 0) + return retval; rmi4_data->f34_query_base_addr = (fd->query_base_addr | (page_number << 8)); @@ -3634,7 +3654,9 @@ static int synaptics_rmi4_f54_init(struct synaptics_rmi4_data *rmi4_data, fhandler->data = NULL; fhandler->extra = NULL; - synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); + retval = synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count); + if (retval < 0) + return retval; rmi4_data->f54_query_base_addr = (fd->query_base_addr | (page_number << 8)); @@ -4127,8 +4149,10 @@ static int synaptics_rmi4_query_device(struct synaptics_rmi4_data *rmi4_data) fhandler->fn_number = rmi_fd.fn_number; fhandler->num_of_data_sources = rmi_fd.intr_src_count; - synaptics_rmi4_set_intr_mask(fhandler, &rmi_fd, - intr_count); + retval = synaptics_rmi4_set_intr_mask( + fhandler, &rmi_fd, intr_count); + if (retval < 0) + return retval; #endif #ifdef F51_DISCRETE_FORCE @@ -4171,6 +4195,8 @@ static int synaptics_rmi4_query_device(struct synaptics_rmi4_data *rmi4_data) dev_dbg(rmi4_data->pdev->dev.parent, "%s: Number of interrupt registers = %d\n", __func__, rmi4_data->num_of_intr_regs); + if (rmi4_data->num_of_intr_regs > MAX_INTR_REGISTERS) + return -EINVAL; f01_query = kmalloc(F01_STD_QUERY_LEN, GFP_KERNEL); if (!f01_query) {