* [PATCH] Input: elan_i2c - prevent division by zero on invalid device parameters
@ 2026-05-13 7:39 Ranjan Kumar
2026-05-13 21:00 ` Dmitry Torokhov
0 siblings, 1 reply; 7+ messages in thread
From: Ranjan Kumar @ 2026-05-13 7:39 UTC (permalink / raw)
To: dmitry.torokhov
Cc: bleung, dusonlin, bentiss, linux-input, linux-kernel,
Ranjan Kumar
The Elan I2C touchpad driver queries the device for its physical
dimensions and trace counts to calculate the device resolution and width.
However, if the device firmware or device tree provides invalid zero
values for x_traces, y_traces, x_mm, or y_mm, it results in a fatal
division-by-zero exception leading to a kernel panic during device probe.
Add sanity checks to ensure these physical parameters are non-zero
before performing the division. If invalid values are detected, log an
error and return -EINVAL to gracefully abort the initialization and
maintain system stability.
Fixes: 6696777c6506 ("Input: add driver for Elan I2C/SMbus touchpad")
Fixes: e3a9a1290688 ("Input: elan_i2c - do not query the info if they are provided")
Signed-off-by: Ranjan Kumar <kumarranja@chromium.org>
---
drivers/input/mouse/elan_i2c_core.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c
index fee1796da3d0..b5fd63928afd 100644
--- a/drivers/input/mouse/elan_i2c_core.c
+++ b/drivers/input/mouse/elan_i2c_core.c
@@ -425,6 +425,14 @@ static int elan_query_device_parameters(struct elan_tp_data *data)
if (error)
return error;
}
+
+ if (unlikely(x_traces == 0 || y_traces == 0)) {
+ dev_err(&client->dev,
+ "Invalid trace numbers: x=%u, y=%u\n",
+ x_traces, y_traces);
+ return -EINVAL;
+ }
+
data->width_x = data->max_x / x_traces;
data->width_y = data->max_y / y_traces;
@@ -440,6 +448,14 @@ static int elan_query_device_parameters(struct elan_tp_data *data)
data->x_res = elan_convert_resolution(hw_x_res, data->pattern);
data->y_res = elan_convert_resolution(hw_y_res, data->pattern);
} else {
+
+ if (unlikely(x_mm == 0 || y_mm == 0)) {
+ dev_err(&client->dev,
+ "Invalid physical dimensions: x_mm=%u, y_mm=%u\n",
+ x_mm, y_mm);
+ return -EINVAL;
+ }
+
data->x_res = (data->max_x + 1) / x_mm;
data->y_res = (data->max_y + 1) / y_mm;
}
--
2.54.0.563.g4f69b47b94-goog
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH] Input: elan_i2c - prevent division by zero on invalid device parameters 2026-05-13 7:39 [PATCH] Input: elan_i2c - prevent division by zero on invalid device parameters Ranjan Kumar @ 2026-05-13 21:00 ` Dmitry Torokhov 2026-05-15 6:52 ` [PATCH v2] " Ranjan Kumar 0 siblings, 1 reply; 7+ messages in thread From: Dmitry Torokhov @ 2026-05-13 21:00 UTC (permalink / raw) To: Ranjan Kumar; +Cc: bleung, dusonlin, bentiss, linux-input, linux-kernel Hi Ranjan, On Wed, May 13, 2026 at 07:39:08AM +0000, Ranjan Kumar wrote: > The Elan I2C touchpad driver queries the device for its physical > dimensions and trace counts to calculate the device resolution and width. > However, if the device firmware or device tree provides invalid zero > values for x_traces, y_traces, x_mm, or y_mm, it results in a fatal > division-by-zero exception leading to a kernel panic during device probe. > Neither crashing nor aborting probe with -EINVAL is great as we will not be able to flash another firmware. How do we get into this state? Is this something actually observed or just theoretical? > Add sanity checks to ensure these physical parameters are non-zero > before performing the division. If invalid values are detected, log an > error and return -EINVAL to gracefully abort the initialization and > maintain system stability. That is hardly "stability" for a laptop when its pointer is not working. Thanks. -- Dmitry ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2] Input: elan_i2c - prevent division by zero on invalid device parameters 2026-05-13 21:00 ` Dmitry Torokhov @ 2026-05-15 6:52 ` Ranjan Kumar 2026-05-15 7:10 ` sashiko-bot 0 siblings, 1 reply; 7+ messages in thread From: Ranjan Kumar @ 2026-05-15 6:52 UTC (permalink / raw) To: dmitry.torokhov; +Cc: bleung, bentiss, linux-input, linux-kernel, Ranjan Kumar The Elan I2C touchpad driver queries the device for its physical dimensions and trace counts to calculate the device resolution and width. However, if the device firmware or device tree provides invalid zero values for x_traces, y_traces, x_mm, or y_mm, it results in a fatal division-by-zero exception leading to a kernel panic during device probe. Add sanity checks to ensure these physical parameters are non-zero before performing the division. If invalid values are detected, log a warning and fall back to safe default values (1) to safely bypass the division. This prevents the kernel panic while allowing the probe to complete successfully. Completing the probe ensures the sysfs nodes are created, keeping the firmware update path intact so a recovery firmware can be flashed to the device. Fixes: 6696777c6506 ("Input: add driver for Elan I2C/SMbus touchpad") Fixes: e3a9a1290688 ("Input: elan_i2c - do not query the info if they are provided") Signed-off-by: Ranjan Kumar <kumarranja@chromium.org> --- Changes in v2: - Changed error handling from aborting probe with -EINVAL to logging a warning and falling back to default values (1). - Bypassing the division instead of aborting preserves the sysfs interface for firmware updates and keeps the pointer functional. drivers/input/mouse/elan_i2c_core.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index fee1796da3d0..32b2849ab36a 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -425,8 +425,17 @@ static int elan_query_device_parameters(struct elan_tp_data *data) if (error) return error; } - data->width_x = data->max_x / x_traces; - data->width_y = data->max_y / y_traces; + + if (unlikely(x_traces == 0 || y_traces == 0)) { + dev_warn(&client->dev, + "invalid trace numbers: x=%u, y=%u\n", + x_traces, y_traces); + data->width_x = 1; + data->width_y = 1; + } else { + data->width_x = data->max_x / x_traces; + data->width_y = data->max_y / y_traces; + } if (device_property_read_u32(&client->dev, "touchscreen-x-mm", &x_mm) || @@ -440,8 +449,16 @@ static int elan_query_device_parameters(struct elan_tp_data *data) data->x_res = elan_convert_resolution(hw_x_res, data->pattern); data->y_res = elan_convert_resolution(hw_y_res, data->pattern); } else { - data->x_res = (data->max_x + 1) / x_mm; - data->y_res = (data->max_y + 1) / y_mm; + if (unlikely(x_mm == 0 || y_mm == 0)) { + dev_warn(&client->dev, + "invalid physical dimensions: x_mm=%u, y_mm=%u\n", + x_mm, y_mm); + data->x_res = 1; + data->y_res = 1; + } else { + data->x_res = (data->max_x + 1) / x_mm; + data->y_res = (data->max_y + 1) / y_mm; + } } if (device_property_read_bool(&client->dev, "elan,clickpad")) -- 2.54.0.563.g4f69b47b94-goog ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2] Input: elan_i2c - prevent division by zero on invalid device parameters 2026-05-15 6:52 ` [PATCH v2] " Ranjan Kumar @ 2026-05-15 7:10 ` sashiko-bot 2026-05-18 6:26 ` [PATCH v3] " Ranjan Kumar 0 siblings, 1 reply; 7+ messages in thread From: sashiko-bot @ 2026-05-15 7:10 UTC (permalink / raw) To: Ranjan Kumar; +Cc: dmitry.torokhov, linux-input Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] Setting `width_x` and `width_y` to 1 as a fallback introduces a severe arithmetic underflow when calculating touch area sizes. -- commit 592cc1df694c917c489ca1a6dcea8bd8b7a8d985 Author: Ranjan Kumar <kumarranja@chromium.org> Input: elan_i2c - prevent division by zero on invalid device parameters The Elan I2C touchpad driver queries the device for its physical dimensions and trace counts to calculate the device resolution and width. If the device provides invalid zero values, this commit adds checks to fall back to safe default values of 1 to bypass the division and prevent a kernel panic. > diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c > index fee1796da3d08..32b2849ab36a7 100644 > --- a/drivers/input/mouse/elan_i2c_core.c > +++ b/drivers/input/mouse/elan_i2c_core.c > @@ -425,8 +425,17 @@ static int elan_query_device_parameters(struct elan_tp_data *data) > if (error) > return error; > } > - data->width_x = data->max_x / x_traces; > - data->width_y = data->max_y / y_traces; > + > + if (unlikely(x_traces == 0 || y_traces == 0)) { > + dev_warn(&client->dev, > + "invalid trace numbers: x=%u, y=%u\n", > + x_traces, y_traces); > + data->width_x = 1; > + data->width_y = 1; Does setting these fallback values to 1 introduce an arithmetic underflow regression when calculating touch area sizes? In elan_report_absolute() and elan_report_contact(), the touch area sizes are calculated using an expression like: area_x = mk_x * (data->width_x - ETP_FWIDTH_REDUCE); Since ETP_FWIDTH_REDUCE is 90 and data->width_x is an unsigned int, setting the width to 1 causes the subtraction to underflow, resulting in a massive unsigned integer. When passed to input_report_abs(), this value is cast back to a negative number, violating the 0 minimum boundary configured for ABS_MT_TOUCH_MAJOR. Could this confuse userspace input handlers and trigger unwanted behaviors? To prevent this underflow while maintaining the firmware update fallback path, should the fallback value be at least ETP_FWIDTH_REDUCE (90) instead of 1? [ ... ] -- Sashiko AI review · https://sashiko.dev/#/patchset/20260515065235.1913403-1-kumarranja@chromium.org?part=1 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v3] Input: elan_i2c - prevent division by zero on invalid device parameters 2026-05-15 7:10 ` sashiko-bot @ 2026-05-18 6:26 ` Ranjan Kumar 2026-06-09 5:18 ` Dmitry Torokhov 0 siblings, 1 reply; 7+ messages in thread From: Ranjan Kumar @ 2026-05-18 6:26 UTC (permalink / raw) To: dmitry.torokhov; +Cc: bleung, bentiss, linux-input, linux-kernel, Ranjan Kumar The Elan I2C touchpad driver queries the device for its physical dimensions and trace counts to calculate the device resolution and width. However, if the device firmware or device tree provides invalid zero values for x_traces, y_traces, x_mm, or y_mm, it results in a fatal division-by-zero exception leading to a kernel panic during device probe. Add sanity checks to ensure these physical parameters are non-zero before performing the division. If invalid trace values are detected, log a warning and fall back to ETP_FWIDTH_REDUCE to prevent arithmetic underflow during touch reporting. For invalid physical dimensions, fall back to a safe default of 1. This prevents the kernel panic while allowing the probe to complete successfully. Completing the probe ensures the sysfs nodes are created, keeping the firmware update path intact so a recovery firmware can be flashed to the device. Fixes: 6696777c6506 ("Input: add driver for Elan I2C/SMbus touchpad") Fixes: e3a9a1290688 ("Input: elan_i2c - do not query the info if they are provided") Signed-off-by: Ranjan Kumar <kumarranja@chromium.org> --- Changes in v3: - Changed trace fallback values from 1 to ETP_FWIDTH_REDUCE to prevent an unsigned integer underflow in elan_report_absolute(). Changes in v2: - Changed error handling from aborting probe with -EINVAL to logging a warning and falling back to default values. drivers/input/mouse/elan_i2c_core.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index fee1796da3d0..c64e1dd1e60b 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -425,8 +425,17 @@ static int elan_query_device_parameters(struct elan_tp_data *data) if (error) return error; } - data->width_x = data->max_x / x_traces; - data->width_y = data->max_y / y_traces; + + if (unlikely(x_traces == 0 || y_traces == 0)) { + dev_warn(&client->dev, + "invalid trace numbers: x=%u, y=%u\n", + x_traces, y_traces); + data->width_x = ETP_FWIDTH_REDUCE; + data->width_y = ETP_FWIDTH_REDUCE; + } else { + data->width_x = data->max_x / x_traces; + data->width_y = data->max_y / y_traces; + } if (device_property_read_u32(&client->dev, "touchscreen-x-mm", &x_mm) || @@ -440,8 +449,16 @@ static int elan_query_device_parameters(struct elan_tp_data *data) data->x_res = elan_convert_resolution(hw_x_res, data->pattern); data->y_res = elan_convert_resolution(hw_y_res, data->pattern); } else { - data->x_res = (data->max_x + 1) / x_mm; - data->y_res = (data->max_y + 1) / y_mm; + if (unlikely(x_mm == 0 || y_mm == 0)) { + dev_warn(&client->dev, + "invalid physical dimensions: x_mm=%u, y_mm=%u\n", + x_mm, y_mm); + data->x_res = 1; + data->y_res = 1; + } else { + data->x_res = (data->max_x + 1) / x_mm; + data->y_res = (data->max_y + 1) / y_mm; + } } if (device_property_read_bool(&client->dev, "elan,clickpad")) -- 2.54.0.563.g4f69b47b94-goog ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v3] Input: elan_i2c - prevent division by zero on invalid device parameters 2026-05-18 6:26 ` [PATCH v3] " Ranjan Kumar @ 2026-06-09 5:18 ` Dmitry Torokhov 2026-06-12 6:03 ` [PATCH v4] Input: elan_i2c - prevent division by zero and arithmetic underflow Ranjan Kumar 0 siblings, 1 reply; 7+ messages in thread From: Dmitry Torokhov @ 2026-06-09 5:18 UTC (permalink / raw) To: Ranjan Kumar; +Cc: bleung, bentiss, linux-input, linux-kernel Hi Ranjan, On Mon, May 18, 2026 at 06:26:24AM +0000, Ranjan Kumar wrote: > The Elan I2C touchpad driver queries the device for its physical > dimensions and trace counts to calculate the device resolution and width. > However, if the device firmware or device tree provides invalid zero > values for x_traces, y_traces, x_mm, or y_mm, it results in a fatal > division-by-zero exception leading to a kernel panic during device probe. > > Add sanity checks to ensure these physical parameters are non-zero > before performing the division. If invalid trace values are detected, > log a warning and fall back to ETP_FWIDTH_REDUCE to prevent arithmetic > underflow during touch reporting. I would define some defaults that are not necessarily the same as ETP_FWIDTH_REDUCE. The arithmetic overflow should be handled separately, as it may still happen if we read (or set up via device tree) some small (but non-zero) values. > For invalid physical dimensions, fall > back to a safe default of 1. > > This prevents the kernel panic while allowing the probe to complete > successfully. Completing the probe ensures the sysfs nodes are created, > keeping the firmware update path intact so a recovery firmware can be > flashed to the device. > > Fixes: 6696777c6506 ("Input: add driver for Elan I2C/SMbus touchpad") > Fixes: e3a9a1290688 ("Input: elan_i2c - do not query the info if they are provided") > Signed-off-by: Ranjan Kumar <kumarranja@chromium.org> > --- > Changes in v3: > - Changed trace fallback values from 1 to ETP_FWIDTH_REDUCE to prevent > an unsigned integer underflow in elan_report_absolute(). > Changes in v2: > - Changed error handling from aborting probe with -EINVAL to logging a > warning and falling back to default values. > > drivers/input/mouse/elan_i2c_core.c | 25 +++++++++++++++++++++---- > 1 file changed, 21 insertions(+), 4 deletions(-) > > diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c > index fee1796da3d0..c64e1dd1e60b 100644 > --- a/drivers/input/mouse/elan_i2c_core.c > +++ b/drivers/input/mouse/elan_i2c_core.c > @@ -425,8 +425,17 @@ static int elan_query_device_parameters(struct elan_tp_data *data) > if (error) > return error; > } > - data->width_x = data->max_x / x_traces; > - data->width_y = data->max_y / y_traces; > + > + if (unlikely(x_traces == 0 || y_traces == 0)) { I'd say "if (!x_traces || !y_traces) ...". This is not hot path so annotating with unlikely does not buy us anything. I wonder if we should be comparing with some threshold instead of 0. Something above 90 I guess. Thanks. -- Dmitry ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v4] Input: elan_i2c - prevent division by zero and arithmetic underflow 2026-06-09 5:18 ` Dmitry Torokhov @ 2026-06-12 6:03 ` Ranjan Kumar 0 siblings, 0 replies; 7+ messages in thread From: Ranjan Kumar @ 2026-06-12 6:03 UTC (permalink / raw) To: dmitry.torokhov; +Cc: bleung, bentiss, linux-input, linux-kernel, Ranjan Kumar The Elan I2C touchpad driver queries the device for its physical dimensions and trace counts to calculate the device resolution and width. However, if the device firmware or device tree provides invalid zero values for x_traces or y_traces, it results in a fatal division-by-zero exception leading to a kernel panic during device probe. Add checks to ensure these parameters are non-zero before performing the division. If invalid trace values are detected, fall back to a safe default of 1. Additionally, prevent an arithmetic underflow in the touch reporting logic. Previously, if the calculated or fallback width was smaller than ETP_FWIDTH_REDUCE (90), the subtraction would underflow, resulting in a massive unsigned integer being reported to userspace. Clamp the adjusted width to a minimum of 0 to safely handle small physical dimensions and fallback scenarios. Completing the probe with safe fallback values ensures the sysfs nodes are created, keeping the firmware update path intact so a recovery firmware can be flashed to the device. Fixes: 6696777c6506 ("Input: add driver for Elan I2C/SMbus touchpad") Fixes: e3a9a1290688 ("Input: elan_i2c - do not query the info if they are provided") Signed-off-by: Ranjan Kumar <kumarranja@chromium.org> --- Changes in v4: - Reverted probe fallback width back to 1. - Added check in elan_report_contact() to clamp adjusted widths to a minimum of 0, fixing the root cause of the arithmetic underflow. Changes in v3: - Changed fallback width from 1 to ETP_FWIDTH_REDUCE to prevent underflow. Changes in v2: - Added check for invalid trace values of 0 to prevent division by zero. drivers/input/mouse/elan_i2c_core.c | 36 ++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index 5cba02a156ce..edb0a28d25aa 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -428,8 +428,17 @@ static int elan_query_device_parameters(struct elan_tp_data *data) if (error) return error; } - data->width_x = data->max_x / x_traces; - data->width_y = data->max_y / y_traces; + + if (!x_traces || !y_traces) { + dev_warn(&client->dev, + "invalid trace numbers: x=%u, y=%u\n", + x_traces, y_traces); + data->width_x = 1; + data->width_y = 1; + } else { + data->width_x = data->max_x / x_traces; + data->width_y = data->max_y / y_traces; + } if (device_property_read_u32(&client->dev, "touchscreen-x-mm", &x_mm) || @@ -443,8 +452,16 @@ static int elan_query_device_parameters(struct elan_tp_data *data) data->x_res = elan_convert_resolution(hw_x_res, data->pattern); data->y_res = elan_convert_resolution(hw_y_res, data->pattern); } else { - data->x_res = (data->max_x + 1) / x_mm; - data->y_res = (data->max_y + 1) / y_mm; + if (unlikely(x_mm == 0 || y_mm == 0)) { + dev_warn(&client->dev, + "invalid physical dimensions: x_mm=%u, y_mm=%u\n", + x_mm, y_mm); + data->x_res = 1; + data->y_res = 1; + } else { + data->x_res = (data->max_x + 1) / x_mm; + data->y_res = (data->max_y + 1) / y_mm; + } } if (device_property_read_bool(&client->dev, "elan,clickpad")) @@ -956,6 +973,7 @@ static void elan_report_contact(struct elan_tp_data *data, int contact_num, if (data->report_features & ETP_FEATURE_REPORT_MK) { unsigned int mk_x, mk_y, area_x, area_y; + int adj_width_x, adj_width_y; u8 mk_data = high_precision ? packet[ETP_MK_DATA_OFFSET + contact_num] : finger_data[3]; @@ -967,8 +985,14 @@ static void elan_report_contact(struct elan_tp_data *data, int contact_num, * To avoid treating large finger as palm, let's reduce * the width x and y per trace. */ - area_x = mk_x * (data->width_x - ETP_FWIDTH_REDUCE); - area_y = mk_y * (data->width_y - ETP_FWIDTH_REDUCE); + + adj_width_x = data->width_x > ETP_FWIDTH_REDUCE ? + data->width_x - ETP_FWIDTH_REDUCE : 0; + adj_width_y = data->width_y > ETP_FWIDTH_REDUCE ? + data->width_y - ETP_FWIDTH_REDUCE : 0; + + area_x = mk_x * adj_width_x; + area_y = mk_y * adj_width_y; input_report_abs(input, ABS_TOOL_WIDTH, mk_x); input_report_abs(input, ABS_MT_TOUCH_MAJOR, -- 2.54.0.1099.g489fc7bff1-goog ^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-06-12 6:05 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-05-13 7:39 [PATCH] Input: elan_i2c - prevent division by zero on invalid device parameters Ranjan Kumar 2026-05-13 21:00 ` Dmitry Torokhov 2026-05-15 6:52 ` [PATCH v2] " Ranjan Kumar 2026-05-15 7:10 ` sashiko-bot 2026-05-18 6:26 ` [PATCH v3] " Ranjan Kumar 2026-06-09 5:18 ` Dmitry Torokhov 2026-06-12 6:03 ` [PATCH v4] Input: elan_i2c - prevent division by zero and arithmetic underflow Ranjan Kumar
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox