⬢ DragonFlyBSD Kernel Audit
DF-3589 / divzero_expr.c
← back to finding ↓ download raw
/*
 * DF-3589 arithmetic proof (userland, same int32 semantics as the kernel).
 *
 * psmsmoother() sys/dev/misc/psm/psm.c:4337 does:
 *      dxp = smoother->squelch_x / (div_x * multiplicator);
 * with div_x clamped to [div_min, div_max] and BOTH div_min, div_max and
 * multiplicator writable by ANY local user through the CTLFLAG_ANYBODY
 * sysctls hw.psm.synaptics.{div_min,div_max,multiplicator}, whose only
 * validation is `arg < 1` (psm.c:5767-5780).
 *
 * 65536 * 65536 wraps to 0 in signed 32-bit arithmetic => the divisor
 * becomes exactly 0 => idiv traps (#DE). In the kernel that is an
 * unrecoverable panic; in userland it is SIGFPE. This program proves the
 * wrap + trap on this exact toolchain.
 */
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	volatile int div_min = 65536, div_max = 65536, multiplicator = 65536;
	volatile int squelch_x = 1234567;
	int div_x, dxp;

	div_x = div_max;			/* imax(div_min, ...) == 65536 */
	printf("div_x=%d multiplicator=%d\n", div_x, multiplicator);
	printf("int32 product div_x*multiplicator = %d (wrapped; 2^32 == 0)\n",
	    div_x * multiplicator);
	fflush(stdout);

	dxp = squelch_x / (div_x * multiplicator);	/* <-- traps here */
	printf("no trap, dxp=%d (BUG NOT REPRODUCED)\n", dxp);
	return (0);
}