⬢ DragonFlyBSD Kernel Audit
DF-3853 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/radeon/radeon_combios.c
+++ b/sys/dev/drm/radeon/radeon_combios.c
@@ -784,6 +784,18 @@
 			mpll->pll_in_max = 500;
 		}
 
+		/* sanitize reference frequencies: a zero value from a crafted
+		 * COMBIOS reaches the divisions in calc_eng_mem_clock()
+		 * (radeon_clocks.c) -> divide by zero -> panic.  The clamp
+		 * block in radeon_get_clock_info() only fixes reference_div.
+		 */
+		if (!p1pll->reference_freq)
+			p1pll->reference_freq = 2700;
+		if (!spll->reference_freq)
+			spll->reference_freq = 2700;
+		if (!mpll->reference_freq)
+			mpll->reference_freq = 2700;
+
 		/* default sclk/mclk */
 		sclk = RBIOS16(pll_info + 0xa);
 		mclk = RBIOS16(pll_info + 0x8);
--- a/sys/dev/drm/radeon/radeon_clocks.c
+++ b/sys/dev/drm/radeon/radeon_clocks.c
@@ -356,6 +356,13 @@
 		    RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) &
 		    RADEON_M_SPLL_REF_DIV_MASK;
 
+	/* defense in depth: combios/atom PLL tables are device-supplied;
+	 * a zero reference frequency would divide by zero below. */
+	if (!spll->reference_freq)
+		spll->reference_freq = 2700;
+	if (!ref_div)
+		ref_div = 12;
+
 	if (req_clock < 15000) {
 		*post_div = 8;
 		req_clock *= 8;