⬢ DragonFlyBSD Kernel Audit
DF-3589 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/misc/psm/psm.c
+++ b/sys/dev/misc/psm/psm.c
@@ -4334,14 +4334,19 @@
 
 		/* Use these averages to calculate x & y. */
 		smoother->squelch_x += smoother->avg_dx;
-		dxp = smoother->squelch_x / (div_x * multiplicator);
-		smoother->squelch_x = smoother->squelch_x %
-		    (div_x * multiplicator);
+		/* DF-3589: the divisor is a product of two sysctl-tunable
+		 * ints; compute it in 64-bit so it can never wrap to zero
+		 * (div_x >= 1 and multiplicator >= 1 => divisor >= 1). */
+		dxp = (int)(smoother->squelch_x /
+		    ((int64_t)div_x * multiplicator));
+		smoother->squelch_x = (int)(smoother->squelch_x %
+		    ((int64_t)div_x * multiplicator));
 
 		smoother->squelch_y += smoother->avg_dy;
-		dyp = smoother->squelch_y / (div_y * multiplicator);
-		smoother->squelch_y = smoother->squelch_y %
-		    (div_y * multiplicator);
+		dyp = (int)(smoother->squelch_y /
+		    ((int64_t)div_y * multiplicator));
+		smoother->squelch_y = (int)(smoother->squelch_y %
+		    ((int64_t)div_y * multiplicator));
 
 		switch(gest->in_vscroll) {
 		case 0: /* Pointer movement. */
@@ -5775,7 +5780,10 @@
 	case SYNAPTICS_SYSCTL_DIV_LEN:
 	case SYNAPTICS_SYSCTL_VSCROLL_DIV_MIN:
 	case SYNAPTICS_SYSCTL_VSCROLL_DIV_MAX:
-		if (arg < 1)
+		/* These values feed 32-bit products that are used as
+		 * divisors in psmsmoother(); bound them far below 2^16
+		 * so no product of two of them can wrap to zero. */
+		if (arg < 1 || arg > 100000)
 			return (EINVAL);
 		break;
 	case SYNAPTICS_SYSCTL_TAP_MAX_DELTA: