DF-3589 / fix.diff
--- 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: |