DragonFlyBSD Kernel Audit
DF-2064 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/drm/i915/intel_uc_fw.c b/sys/dev/drm/i915/intel_uc_fw.c
--- a/sys/dev/drm/i915/intel_uc_fw.c
+++ b/sys/dev/drm/i915/intel_uc_fw.c
@@ -80,6 +80,13 @@
 
 	/* Firmware bits always start from header */
 	uc_fw->header_offset = 0;
+	if (css->modulus_size_dw + css->key_size_dw + css->exponent_size_dw >
+		    css->header_size_dw) {
+		DRM_WARN("%s: Firmware CSS header size fields underflow\n",
+			 intel_uc_fw_type_repr(uc_fw->type));
+		err = -ENOEXEC;
+		goto fail;
+	}
 	uc_fw->header_size = (css->header_size_dw - css->modulus_size_dw -
 			      css->key_size_dw - css->exponent_size_dw) *
 			     sizeof(u32);
@@ -93,6 +100,12 @@
 
 	/* then, uCode */
 	uc_fw->ucode_offset = uc_fw->header_offset + uc_fw->header_size;
+	if (css->size_dw < css->header_size_dw) {
+		DRM_WARN("%s: Firmware uCode size underflow\n",
+			 intel_uc_fw_type_repr(uc_fw->type));
+		err = -ENOEXEC;
+		goto fail;
+	}
 	uc_fw->ucode_size = (css->size_dw - css->header_size_dw) * sizeof(u32);
 
 	/* now RSA */
@@ -106,7 +119,11 @@
 	uc_fw->rsa_size = css->key_size_dw * sizeof(u32);
 
 	/* At least, it should have header, uCode and RSA. Size of all three. */
-	size = uc_fw->header_size + uc_fw->ucode_size + uc_fw->rsa_size;
+	/* Promote to size_t before summing: all three are u32 and their
+	 * sum can overflow 32 bits, bypassing the truncation check below.
+	 */
+	size = (size_t)uc_fw->header_size + (size_t)uc_fw->ucode_size +
+	    (size_t)uc_fw->rsa_size;
 	if (fw->datasize < size) {
 		DRM_WARN("%s: Truncated firmware (%zu, expected %zu)\n",
 			 intel_uc_fw_type_repr(uc_fw->type), fw->datasize, size);