mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] HID: wacom: avoid overflows in sequence number tracking
@ 2026-09-15 11:14 Aldo Ariel Panzardo
  2026-09-15 14:16 ` [PATCH v2] " Aldo Ariel Panzardo
  2026-09-15 14:52 ` [PATCH v3] " Aldo Ariel Panzardo
  0 siblings, 2 replies; 8+ messages in thread
From: Aldo Ariel Panzardo @ 2026-09-15 11:14 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires
  Cc: Ping Cheng, Jason Gerecke, linux-input, linux-kernel, stable,
	Aldo Ariel Panzardo

The dropped-packet calculation derives the sequence range in signed
int arithmetic. A sequence field whose logical range spans all signed
32-bit values makes the range calculation wrap to zero, so the following
modulo triggers a divide exception.

Do the range and delta calculations in s64, and normalize the delta after
the modulo. Also avoid overflowing value + 1 when the received value is at
the logical maximum.

Fixes: 359673ea3a20 ("HID: wacom: Support sequence numbers smaller than 16-bit")
Cc: stable@vger.kernel.org
Signed-off-by: Aldo Ariel Panzardo <qwe.aldo@gmail.com>
---
 drivers/hid/wacom_wac.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index da1f0ea856..39ffe5e7c7 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -2530,13 +2530,21 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
 	case WACOM_HID_WD_SEQUENCENUMBER:
 		if (wacom_wac->hid_data.sequence_number != value &&
 		    wacom_wac->hid_data.sequence_number >= 0) {
-			int sequence_size = field->logical_maximum - field->logical_minimum + 1;
-			int drop_count = (value - wacom_wac->hid_data.sequence_number) % sequence_size;
-			hid_warn(hdev, "Dropped %d packets", drop_count);
+			s64 sequence_size = (s64)field->logical_maximum -
+					    field->logical_minimum + 1;
+			s64 drop_count = (s64)value -
+					 wacom_wac->hid_data.sequence_number;
+
+			drop_count %= sequence_size;
+			if (drop_count < 0)
+				drop_count += sequence_size;
+			hid_warn(hdev, "Dropped %lld packets",
+				 (long long)drop_count);
 		}
-		wacom_wac->hid_data.sequence_number = value + 1;
-		if (wacom_wac->hid_data.sequence_number > field->logical_maximum)
+		if (value >= field->logical_maximum)
 			wacom_wac->hid_data.sequence_number = field->logical_minimum;
+		else
+			wacom_wac->hid_data.sequence_number = value + 1;
 		return;
 	}
 
-- 
2.43.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v2] HID: wacom: avoid overflows in sequence number tracking
  2026-09-15 11:14 [PATCH] HID: wacom: avoid overflows in sequence number tracking Aldo Ariel Panzardo
@ 2026-09-15 14:16 ` Aldo Ariel Panzardo
  2026-09-16 18:13   ` kernel test robot
  2026-09-17  5:06   ` kernel test robot
  2026-09-15 14:52 ` [PATCH v3] " Aldo Ariel Panzardo
  1 sibling, 2 replies; 8+ messages in thread
From: Aldo Ariel Panzardo @ 2026-09-15 14:16 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires
  Cc: Ping Cheng, Jason Gerecke, linux-input, linux-kernel, stable,
	Aldo Ariel Panzardo

The dropped-packet calculation derives the sequence range in signed int
arithmetic. A sequence field whose logical range spans all 32-bit values
makes the range calculation wrap to zero, so the following modulo triggers
a divide exception.

Normalize the maximum and current value according to the HID parser's
signedness rule, and keep the sequence state and arithmetic in s64. This
also avoids overflowing value + 1 at the logical maximum.

Fixes: 359673ea3a20 ("HID: wacom: Support sequence numbers smaller than 16-bit")
Cc: stable@vger.kernel.org
Signed-off-by: Aldo Ariel Panzardo <qwe.aldo@gmail.com>
---
 drivers/hid/wacom_wac.c | 32 ++++++++++++++++++++++++--------
 drivers/hid/wacom_wac.h |  2 +-
 2 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index da1f0ea856..428ac7077a 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -2527,18 +2527,34 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
 	case WACOM_HID_WD_BARRELSWITCH3:
 		wacom_wac->hid_data.barrelswitch3 = value;
 		return;
-	case WACOM_HID_WD_SEQUENCENUMBER:
-		if (wacom_wac->hid_data.sequence_number != value &&
+	case WACOM_HID_WD_SEQUENCENUMBER: {
+		s64 sequence_minimum = field->logical_minimum;
+		s64 sequence_maximum = sequence_minimum < 0 ?
+			(s64)field->logical_maximum :
+			(s64)(u32)field->logical_maximum;
+		s64 sequence_value = sequence_minimum < 0 ?
+			(s64)value : (s64)(u32)value;
+
+		if (wacom_wac->hid_data.sequence_number != sequence_value &&
 		    wacom_wac->hid_data.sequence_number >= 0) {
-			int sequence_size = field->logical_maximum - field->logical_minimum + 1;
-			int drop_count = (value - wacom_wac->hid_data.sequence_number) % sequence_size;
-			hid_warn(hdev, "Dropped %d packets", drop_count);
+			s64 sequence_size = sequence_maximum -
+					    sequence_minimum + 1;
+			s64 drop_count = sequence_value -
+					 wacom_wac->hid_data.sequence_number;
+
+			drop_count %= sequence_size;
+			if (drop_count < 0)
+				drop_count += sequence_size;
+			hid_warn(hdev, "Dropped %lld packets",
+				 (long long)drop_count);
 		}
-		wacom_wac->hid_data.sequence_number = value + 1;
-		if (wacom_wac->hid_data.sequence_number > field->logical_maximum)
-			wacom_wac->hid_data.sequence_number = field->logical_minimum;
+		if (sequence_value >= sequence_maximum)
+			wacom_wac->hid_data.sequence_number = sequence_minimum;
+		else
+			wacom_wac->hid_data.sequence_number = sequence_value + 1;
 		return;
 	}
+	}
 
 	/* send pen events only when touch is up or forced out
 	 * or touch arbitration is off
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 126bec6e5c..74e7c5a04a 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -324,7 +324,7 @@ struct hid_data {
 	int bat_connected;
 	int ps_connected;
 	bool pad_input_event_flag;
-	int sequence_number;
+	s64 sequence_number;
 	ktime_t time_delayed;
 };
 
-- 
2.43.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v3] HID: wacom: avoid overflows in sequence number tracking
  2026-09-15 11:14 [PATCH] HID: wacom: avoid overflows in sequence number tracking Aldo Ariel Panzardo
  2026-09-15 14:16 ` [PATCH v2] " Aldo Ariel Panzardo
@ 2026-09-15 14:52 ` Aldo Ariel Panzardo
  2026-11-05 19:20   ` Jason Gerecke
  1 sibling, 1 reply; 8+ messages in thread
From: Aldo Ariel Panzardo @ 2026-09-15 14:52 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires
  Cc: Ping Cheng, Jason Gerecke, linux-input, linux-kernel, stable,
	Aldo Ariel Panzardo

The dropped-packet calculation derives the sequence range in signed int
arithmetic. A sequence field whose logical range spans all 32-bit values
makes the range calculation wrap to zero, so the following modulo triggers
a divide exception.

Normalize the maximum and current value according to the HID parser's
signedness rule, and keep the sequence state and arithmetic in s64. Use
div64_s64() for the remainder to avoid __moddi3 link failures on 32-bit
architectures. This also avoids overflowing value + 1 at the logical
maximum.

Fixes: 359673ea3a20 ("HID: wacom: Support sequence numbers smaller than 16-bit")
Cc: stable@vger.kernel.org
Signed-off-by: Aldo Ariel Panzardo <qwe.aldo@gmail.com>
---

Changes in v3:
  - Replace raw s64 modulo with div64_s64()-based remainder to avoid
    __moddi3 link failure on 32-bit architectures (i386, arm32).
    Reported by Sashiko AI review.

Changes in v2:
  - Normalize logical_maximum/value as unsigned when logical_minimum >= 0,
    matching HID parser signedness. Store sequence state as s64.
    Fixes unsigned 0..UINT32_MAX range that broke v1.

 drivers/hid/wacom_wac.c | 33 ++++++++++++++++++++++++---------
 drivers/hid/wacom_wac.h |  2 +-
 2 files changed, 25 insertions(+), 10 deletions(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index da1f0ea856..af94f59a5d 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -7,6 +7,7 @@
 #include "wacom.h"
 #include <linux/input/mt.h>
 #include <linux/jiffies.h>
+#include <linux/math64.h>

 /* resolution for penabled devices */
 #define WACOM_PL_RES		20
@@ -2527,18 +2528,33 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
 	case WACOM_HID_WD_BARRELSWITCH3:
 		wacom_wac->hid_data.barrelswitch3 = value;
 		return;
-	case WACOM_HID_WD_SEQUENCENUMBER:
-		if (wacom_wac->hid_data.sequence_number != value &&
+	case WACOM_HID_WD_SEQUENCENUMBER: {
+		s64 sequence_minimum = field->logical_minimum;
+		s64 sequence_maximum = sequence_minimum < 0 ?
+			(s64)field->logical_maximum :
+			(s64)(u32)field->logical_maximum;
+		s64 sequence_value = sequence_minimum < 0 ?
+			(s64)value : (s64)(u32)value;
+
+		if (wacom_wac->hid_data.sequence_number != sequence_value &&
 		    wacom_wac->hid_data.sequence_number >= 0) {
-			int sequence_size = field->logical_maximum - field->logical_minimum + 1;
-			int drop_count = (value - wacom_wac->hid_data.sequence_number) % sequence_size;
-			hid_warn(hdev, "Dropped %d packets", drop_count);
+			s64 sequence_size = sequence_maximum -
+					    sequence_minimum + 1;
+			s64 drop_count = sequence_value -
+					 wacom_wac->hid_data.sequence_number;
+
+			drop_count -= div64_s64(drop_count, sequence_size) *
+				      sequence_size;
+			if (drop_count < 0)
+				drop_count += sequence_size;
+			hid_warn(hdev, "Dropped %lld packets",
+				 (long long)drop_count);
 		}
-		wacom_wac->hid_data.sequence_number = value + 1;
-		if (wacom_wac->hid_data.sequence_number > field->logical_maximum)
-			wacom_wac->hid_data.sequence_number = field->logical_minimum;
+		if (sequence_value >= sequence_maximum)
+			wacom_wac->hid_data.sequence_number = sequence_minimum;
+		else
+			wacom_wac->hid_data.sequence_number = sequence_value + 1;
 		return;
 	}
+	}

 	/* send pen events only when touch is up or forced out
 	 * or touch arbitration is off
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 126bec6e5c..74e7c5a04a 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -324,7 +324,7 @@ struct hid_data {
 	int bat_connected;
 	int ps_connected;
 	bool pad_input_event_flag;
-	int sequence_number;
+	s64 sequence_number;
 	ktime_t time_delayed;
 };

--
2.43.0

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2] HID: wacom: avoid overflows in sequence number tracking
  2026-09-15 14:16 ` [PATCH v2] " Aldo Ariel Panzardo
@ 2026-09-16 18:13   ` kernel test robot
  2026-09-17  5:06   ` kernel test robot
  1 sibling, 0 replies; 8+ messages in thread
From: kernel test robot @ 2026-09-16 18:13 UTC (permalink / raw)
  To: Aldo Ariel Panzardo, Jiri Kosina, Benjamin Tissoires
  Cc: oe-kbuild-all, Ping Cheng, Jason Gerecke, linux-input,
	linux-kernel, stable, Aldo Ariel Panzardo

Hi Aldo,

kernel test robot noticed the following build errors:

[auto build test ERROR on hid/for-next]
[also build test ERROR on linus/master v7.3-rc3 next-20260914]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Aldo-Ariel-Panzardo/HID-wacom-avoid-overflows-in-sequence-number-tracking/20260915-111621
base:   https://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git for-next
patch link:    https://lore.kernel.org/r/20260915141621.3011011-1-qwe.aldo%40gmail.com
patch subject: [PATCH v2] HID: wacom: avoid overflows in sequence number tracking
config: arm-randconfig-1001-20260916 (https://download.01.org/0day-ci/archive/20260917/202609170218.u9lMtoL0-lkp@intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 8.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260917/202609170218.u9lMtoL0-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202609170218.u9lMtoL0-lkp@intel.com/

All errors (new ones prefixed by >>, old ones prefixed by <<):

>> ERROR: modpost: drivers/hid/wacom.ko: symbol '__aeabi_ldivmod' undefined!

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2] HID: wacom: avoid overflows in sequence number tracking
  2026-09-15 14:16 ` [PATCH v2] " Aldo Ariel Panzardo
  2026-09-16 18:13   ` kernel test robot
@ 2026-09-17  5:06   ` kernel test robot
  1 sibling, 0 replies; 8+ messages in thread
From: kernel test robot @ 2026-09-17  5:06 UTC (permalink / raw)
  To: Aldo Ariel Panzardo, Jiri Kosina, Benjamin Tissoires
  Cc: llvm, oe-kbuild-all, Ping Cheng, Jason Gerecke, linux-input,
	linux-kernel, stable, Aldo Ariel Panzardo

Hi Aldo,

kernel test robot noticed the following build errors:

[auto build test ERROR on hid/for-next]
[also build test ERROR on linus/master v7.3-rc3]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Aldo-Ariel-Panzardo/HID-wacom-avoid-overflows-in-sequence-number-tracking/20260915-111621
base:   https://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git for-next
patch link:    https://lore.kernel.org/r/20260915141621.3011011-1-qwe.aldo%40gmail.com
patch subject: [PATCH v2] HID: wacom: avoid overflows in sequence number tracking
config: hexagon-allmodconfig (https://download.01.org/0day-ci/archive/20260917/202609171246.TbpsuolV-lkp@intel.com/config)
compiler: clang version 24.0.0git (https://github.com/llvm/llvm-project 148ee2b266b73a49f1f31d0bd17d4818b91bee9f)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260917/202609171246.TbpsuolV-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202609171246.TbpsuolV-lkp@intel.com/

All errors (new ones prefixed by >>, old ones prefixed by <<):

>> ERROR: modpost: drivers/hid/wacom.ko: symbol '__hexagon_moddi3' undefined!

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v3] HID: wacom: avoid overflows in sequence number tracking
  2026-09-15 14:52 ` [PATCH v3] " Aldo Ariel Panzardo
@ 2026-11-05 19:20   ` Jason Gerecke
  2026-11-06 12:04     ` [PATCH v4] HID: wacom: avoid divide exception in dropped-packet calculation Aldo Ariel Panzardo
  0 siblings, 1 reply; 8+ messages in thread
From: Jason Gerecke @ 2026-11-05 19:20 UTC (permalink / raw)
  To: Aldo Ariel Panzardo
  Cc: Jiri Kosina, Benjamin Tissoires, Ping Cheng, Jason Gerecke,
	linux-input, linux-kernel, stable

On Tue, Sep 15, 2026 at 9:17 AM Aldo Ariel Panzardo <qwe.aldo@gmail.com> wrote:
>
> The dropped-packet calculation derives the sequence range in signed int
> arithmetic. A sequence field whose logical range spans all 32-bit values
> makes the range calculation wrap to zero, so the following modulo triggers
> a divide exception.
>
> Normalize the maximum and current value according to the HID parser's
> signedness rule, and keep the sequence state and arithmetic in s64. Use
> div64_s64() for the remainder to avoid __moddi3 link failures on 32-bit
> architectures. This also avoids overflowing value + 1 at the logical
> maximum.
>
> Fixes: 359673ea3a20 ("HID: wacom: Support sequence numbers smaller than 16-bit")
> Cc: stable@vger.kernel.org
> Signed-off-by: Aldo Ariel Panzardo <qwe.aldo@gmail.com>
> ---

Generally speaking, I feel like NAK-ing this patch as it currently is.
I'm happy to take a patch that specifically addresses the divide
exception, without expanding the size of sequence_number (mostly
because that particular part is a bit unnecessary with our hardware
unlikely to ever spend more than 32 bits on a sequence number). It
should be possible to introduce a helper function that calculates the
value with a branch rather than explicit division, e.g. something
like:

int wrapped_dist(int after, int before, int min, int max) {
        if (after >= before) {
               return after - before;
        }
       else {
              return (max - before) + (after - min) + 1;
       }
}

Jason (she/they)
---
Now instead of four in the eights place /
you’ve got three, ‘Cause you added one  /
(That is to say, eight) to the two,     /
But you can’t take seven from three,    /
So you look at the sixty-fours....

>
> Changes in v3:
>   - Replace raw s64 modulo with div64_s64()-based remainder to avoid
>     __moddi3 link failure on 32-bit architectures (i386, arm32).
>     Reported by Sashiko AI review.
>
> Changes in v2:
>   - Normalize logical_maximum/value as unsigned when logical_minimum >= 0,
>     matching HID parser signedness. Store sequence state as s64.
>     Fixes unsigned 0..UINT32_MAX range that broke v1.
>
>  drivers/hid/wacom_wac.c | 33 ++++++++++++++++++++++++---------
>  drivers/hid/wacom_wac.h |  2 +-
>  2 files changed, 25 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
> index da1f0ea856..af94f59a5d 100644
> --- a/drivers/hid/wacom_wac.c
> +++ b/drivers/hid/wacom_wac.c
> @@ -7,6 +7,7 @@
>  #include "wacom.h"
>  #include <linux/input/mt.h>
>  #include <linux/jiffies.h>
> +#include <linux/math64.h>
>
>  /* resolution for penabled devices */
>  #define WACOM_PL_RES           20
> @@ -2527,18 +2528,33 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
>         case WACOM_HID_WD_BARRELSWITCH3:
>                 wacom_wac->hid_data.barrelswitch3 = value;
>                 return;
> -       case WACOM_HID_WD_SEQUENCENUMBER:
> -               if (wacom_wac->hid_data.sequence_number != value &&
> +       case WACOM_HID_WD_SEQUENCENUMBER: {
> +               s64 sequence_minimum = field->logical_minimum;
> +               s64 sequence_maximum = sequence_minimum < 0 ?
> +                       (s64)field->logical_maximum :
> +                       (s64)(u32)field->logical_maximum;
> +               s64 sequence_value = sequence_minimum < 0 ?
> +                       (s64)value : (s64)(u32)value;
> +
> +               if (wacom_wac->hid_data.sequence_number != sequence_value &&
>                     wacom_wac->hid_data.sequence_number >= 0) {
> -                       int sequence_size = field->logical_maximum - field->logical_minimum + 1;
> -                       int drop_count = (value - wacom_wac->hid_data.sequence_number) % sequence_size;
> -                       hid_warn(hdev, "Dropped %d packets", drop_count);
> +                       s64 sequence_size = sequence_maximum -
> +                                           sequence_minimum + 1;
> +                       s64 drop_count = sequence_value -
> +                                        wacom_wac->hid_data.sequence_number;
> +
> +                       drop_count -= div64_s64(drop_count, sequence_size) *
> +                                     sequence_size;
> +                       if (drop_count < 0)
> +                               drop_count += sequence_size;
> +                       hid_warn(hdev, "Dropped %lld packets",
> +                                (long long)drop_count);
>                 }
> -               wacom_wac->hid_data.sequence_number = value + 1;
> -               if (wacom_wac->hid_data.sequence_number > field->logical_maximum)
> -                       wacom_wac->hid_data.sequence_number = field->logical_minimum;
> +               if (sequence_value >= sequence_maximum)
> +                       wacom_wac->hid_data.sequence_number = sequence_minimum;
> +               else
> +                       wacom_wac->hid_data.sequence_number = sequence_value + 1;
>                 return;
>         }
> +       }
>
>         /* send pen events only when touch is up or forced out
>          * or touch arbitration is off
> diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
> index 126bec6e5c..74e7c5a04a 100644
> --- a/drivers/hid/wacom_wac.h
> +++ b/drivers/hid/wacom_wac.h
> @@ -324,7 +324,7 @@ struct hid_data {
>         int bat_connected;
>         int ps_connected;
>         bool pad_input_event_flag;
> -       int sequence_number;
> +       s64 sequence_number;
>         ktime_t time_delayed;
>  };
>
> --
> 2.43.0
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v4] HID: wacom: avoid divide exception in dropped-packet calculation
  2026-11-05 19:20   ` Jason Gerecke
@ 2026-11-06 12:04     ` Aldo Ariel Panzardo
  2026-11-06 18:46       ` Jason Gerecke
  0 siblings, 1 reply; 8+ messages in thread
From: Aldo Ariel Panzardo @ 2026-11-06 12:04 UTC (permalink / raw)
  To: Jason Gerecke
  Cc: Jiri Kosina, Benjamin Tissoires, Ping Cheng, Jason Gerecke,
	linux-input, linux-kernel, stable

The dropped-packet calculation uses a modulo against sequence_size
(logical_maximum - logical_minimum + 1).  When a HID descriptor
declares a sequence field whose logical range spans all 32-bit
values, sequence_size wraps to zero and the modulo triggers a
divide exception.

Replace the division-based calculation with a branch that computes
the forward distance through the sequence range directly, as
suggested by Jason Gerecke.  This keeps the existing int types and
avoids the divide-by-zero without any 64-bit arithmetic.

Fixes: 359673ea3a20 ("HID: wacom: Support sequence numbers smaller than 16-bit")
Cc: stable@vger.kernel.org
Suggested-by: Jason Gerecke <jason.gerecke@wacom.com>
Signed-off-by: Aldo Ariel Panzardo <qwe.aldo@gmail.com>
---

Changes in v4:
- Replace s64 arithmetic with a branch-based helper that computes
  the forward wrapped distance directly, as suggested by Jason Gerecke.
  Keeps sequence_number as int; no type changes needed.

Changes in v3:
- Replace raw s64 modulo with div64_s64()-based remainder to avoid
  __moddi3 link failure on 32-bit architectures (i386, arm32).

Changes in v2:
- Normalize logical_maximum/value as unsigned when logical_minimum >= 0,
  matching HID parser signedness. Store sequence state as s64.

 drivers/hid/wacom_wac.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 361738b..1d3ae94 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -2426,6 +2426,13 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
 	}
 }
 
+static int wacom_hid_wrapped_dist(int after, int before, int min, int max)
+{
+	if (after >= before)
+		return after - before;
+	return (max - before) + (after - min) + 1;
+}
+
 static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 		struct hid_usage *usage, __s32 value)
 {
@@ -2551,8 +2558,11 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
 	case WACOM_HID_WD_SEQUENCENUMBER:
 		if (wacom_wac->hid_data.sequence_number != value &&
 		    wacom_wac->hid_data.sequence_number >= 0) {
-			int sequence_size = field->logical_maximum - field->logical_minimum + 1;
-			int drop_count = (value - wacom_wac->hid_data.sequence_number) % sequence_size;
+			int drop_count = wacom_hid_wrapped_dist(
+				value,
+				wacom_wac->hid_data.sequence_number,
+				field->logical_minimum,
+				field->logical_maximum);
 			hid_warn(hdev, "Dropped %d packets", drop_count);
 		}
 		wacom_wac->hid_data.sequence_number = value + 1;
-- 
2.53.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v4] HID: wacom: avoid divide exception in dropped-packet calculation
  2026-11-06 12:04     ` [PATCH v4] HID: wacom: avoid divide exception in dropped-packet calculation Aldo Ariel Panzardo
@ 2026-11-06 18:46       ` Jason Gerecke
  0 siblings, 0 replies; 8+ messages in thread
From: Jason Gerecke @ 2026-11-06 18:46 UTC (permalink / raw)
  To: Aldo Ariel Panzardo
  Cc: Jiri Kosina, Benjamin Tissoires, Ping Cheng, Jason Gerecke,
	linux-input, linux-kernel, stable

On Fri, Nov 6, 2026 at 4:04 AM Aldo Ariel Panzardo <qwe.aldo@gmail.com> wrote:
>
> The dropped-packet calculation uses a modulo against sequence_size
> (logical_maximum - logical_minimum + 1).  When a HID descriptor
> declares a sequence field whose logical range spans all 32-bit
> values, sequence_size wraps to zero and the modulo triggers a
> divide exception.
>
> Replace the division-based calculation with a branch that computes
> the forward distance through the sequence range directly, as
> suggested by Jason Gerecke.  This keeps the existing int types and
> avoids the divide-by-zero without any 64-bit arithmetic.
>
> Fixes: 359673ea3a20 ("HID: wacom: Support sequence numbers smaller than 16-bit")
> Cc: stable@vger.kernel.org
> Suggested-by: Jason Gerecke <jason.gerecke@wacom.com>
> Signed-off-by: Aldo Ariel Panzardo <qwe.aldo@gmail.com>

Much happier with this version! Thanks!!

Reviewed-by: Jason Gerecke <jason.gerecke@wacom.com>

Jason (she/they)
---
Now instead of four in the eights place /
you’ve got three, ‘Cause you added one  /
(That is to say, eight) to the two,     /
But you can’t take seven from three,    /
So you look at the sixty-fours....

> ---
>
> Changes in v4:
> - Replace s64 arithmetic with a branch-based helper that computes
>   the forward wrapped distance directly, as suggested by Jason Gerecke.
>   Keeps sequence_number as int; no type changes needed.
>
> Changes in v3:
> - Replace raw s64 modulo with div64_s64()-based remainder to avoid
>   __moddi3 link failure on 32-bit architectures (i386, arm32).
>
> Changes in v2:
> - Normalize logical_maximum/value as unsigned when logical_minimum >= 0,
>   matching HID parser signedness. Store sequence state as s64.
>
>  drivers/hid/wacom_wac.c | 14 ++++++++++++--
>  1 file changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
> index 361738b..1d3ae94 100644
> --- a/drivers/hid/wacom_wac.c
> +++ b/drivers/hid/wacom_wac.c
> @@ -2426,6 +2426,13 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
>         }
>  }
>
> +static int wacom_hid_wrapped_dist(int after, int before, int min, int max)
> +{
> +       if (after >= before)
> +               return after - before;
> +       return (max - before) + (after - min) + 1;
> +}
> +
>  static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
>                 struct hid_usage *usage, __s32 value)
>  {
> @@ -2551,8 +2558,11 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
>         case WACOM_HID_WD_SEQUENCENUMBER:
>                 if (wacom_wac->hid_data.sequence_number != value &&
>                     wacom_wac->hid_data.sequence_number >= 0) {
> -                       int sequence_size = field->logical_maximum - field->logical_minimum + 1;
> -                       int drop_count = (value - wacom_wac->hid_data.sequence_number) % sequence_size;
> +                       int drop_count = wacom_hid_wrapped_dist(
> +                               value,
> +                               wacom_wac->hid_data.sequence_number,
> +                               field->logical_minimum,
> +                               field->logical_maximum);
>                         hid_warn(hdev, "Dropped %d packets", drop_count);
>                 }
>                 wacom_wac->hid_data.sequence_number = value + 1;
> --
> 2.53.0
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-11-06 18:46 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-15 11:14 [PATCH] HID: wacom: avoid overflows in sequence number tracking Aldo Ariel Panzardo
2026-09-15 14:16 ` [PATCH v2] " Aldo Ariel Panzardo
2026-09-16 18:13   ` kernel test robot
2026-09-17  5:06   ` kernel test robot
2026-09-15 14:52 ` [PATCH v3] " Aldo Ariel Panzardo
2026-11-05 19:20   ` Jason Gerecke
2026-11-06 12:04     ` [PATCH v4] HID: wacom: avoid divide exception in dropped-packet calculation Aldo Ariel Panzardo
2026-11-06 18:46       ` Jason Gerecke

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®