⬢ DragonFlyBSD Kernel Audit
DF-5213 / fix.diff
← back to finding ↓ download raw
# DF-5213 - amdgpu df_v3_6_funcs leaves enable_ecc_force_par_wr_rmw NULL
# (incomplete vtable; latent NULL-deref)
#
# struct amdgpu_df_funcs declares .enable_ecc_force_par_wr_rmw
# (sys/dev/drm/amd/amdgpu/amdgpu.h:781-782) but df_v3_6_funcs
# (df_v3_6.c:108-116, the CHIP_VEGA20 table per soc15.c:519-520)
# initializes only 6 of the 7 members. The sole call site
# (gmc_v9_0.c:759, gmc_v9_0_late_init) is currently gated on
# asic_type == CHIP_VEGA10 (gmc_v9_0.c:753), which uses df_v1_7_funcs
# (implements the op, df_v1_7.c:119) - so the NULL slot is not
# dispatched today; any future Vega20-reachable caller (or a widening
# of the asic gate, as repeatedly happened to this ECC path upstream)
# turns it into a boot-time NULL function-pointer dereference.
#
# Fix: guard the indirect call (cheap, behavior-preserving; matches the
# drm convention for optional vtable ops). Shape identical to upstream
# Linux, which carries the same latent gap.
#
# Not compile-validated (full drm/amdgpu module build is out of scope
# for this Info-grade finding; the change is a pure NULL-guard on an
# existing expression). Authored post-verification; never applied to
# the read-only sys/ tree.

--- a/sys/dev/drm/amd/amdgpu/gmc_v9_0.c	2026-10-01 04:19:41.034197941 +0000
+++ b/sys/dev/drm/amd/amdgpu/gmc_v9_0.c	2026-10-01 04:19:41.046197788 +0000
@@ -756,7 +756,13 @@
 			DRM_INFO("ECC is active.\n");
 		} else if (r == 0) {
 			DRM_INFO("ECC is not present.\n");
-			adev->df_funcs->enable_ecc_force_par_wr_rmw(adev, false);
+			/*
+			 * df_v3_6_funcs (VEGA20) does not implement
+			 * enable_ecc_force_par_wr_rmw - guard the
+			 * indirect call against the NULL slot.
+			 */
+			if (adev->df_funcs->enable_ecc_force_par_wr_rmw)
+				adev->df_funcs->enable_ecc_force_par_wr_rmw(adev, false);
 		} else {
 			DRM_ERROR("gmc_v9_0_ecc_available() failed. r: %d\n", r);
 			return r;