DF-4224 / fix.diff
--- a/sys/dev/drm/drm_modes.c +++ b/sys/dev/drm/drm_modes.c @@ -1460,16 +1460,24 @@ bool drm_mode_parse_command_line_for_con switch (name[i]) { case '@': if (!refresh_specified && !bpp_specified && !yres_specified && !cvt && !rb && was_digit) { - refresh = simple_strtol(&name[i+1], NULL, 10); + long val = simple_strtol(&name[i+1], NULL, 10); + + /* struct drm_cmdline_mode stores refresh/bpp in + * int. Values > INT_MAX (or negative) wrap and + * later drive divide-by-zero panics in + * drm_cvt_mode()/drm_gtf_mode_complex() + * (vfieldrate -> hperiod/hfreq_est math). + */ + if (val < 0 || val > INT_MAX) + goto done; + refresh = val; refresh_specified = true; was_digit = false; } else goto done; break; case '-': if (!bpp_specified && !yres_specified && !cvt && !rb && was_digit) { - bpp = simple_strtol(&name[i+1], NULL, 10); + long val = simple_strtol(&name[i+1], NULL, 10); + + if (val < 0 || val > INT_MAX) + goto done; + bpp = val; bpp_specified = true; was_digit = false; } else goto done; @@ -171,6 +179,12 @@ struct drm_display_mode *drm_cvt_mode(str /* the required field fresh rate */ if (interlaced) vfieldrate = vrefresh * 2; else vfieldrate = vrefresh; + + /* Defensive: reject absurd field rates before the hperiod math. + * Values like 134217728 wrap hfreq/hperiod products to 0 and + * panic on the divisions below. + */ + if (vfieldrate == 0 || vfieldrate > 1000) { + drm_mode_destroy(dev, drm_mode); + return NULL; + } /* horizontal pixels */ hdisplay_rnd = hdisplay - (hdisplay % CVT_H_GRANULARITY); @@ -415,6 +429,13 @@ drm_gtf_mode_complex(struct drm_device * if (interlaced) vfieldrate_rqd = vrefresh * 2; else vfieldrate_rqd = vrefresh; + + /* Defensive: reject absurd field rates before the hfreq_est math + * (e.g. 134217728 makes tmp2*1000*vfieldrate_rqd wrap to 0, so + * hfreq_est == 0 and the GTF_M_PRIME division traps). + */ + if (vfieldrate_rqd == 0 || vfieldrate_rqd > 1000) { + drm_mode_destroy(dev, drm_mode); + return NULL; + } /* 4. Find number of lines in Top margin: */ top_margin = 0; |