DF-2064 / fix.diff
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); |