aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2026-05-27 20:18:05 +0000
committerMark Johnston <markj@FreeBSD.org>2026-08-19 19:00:58 +0000
commitc905b341204e92ce18c84b9ac33b643222c36d65 (patch)
tree7ac6102b701b1b0597a8d8cb319d4bd6d81f32fc
parent6fb0f132755829c7594cc482023cff6347ed9b25 (diff)
ucode: Fix validation on Intel platforms
The check for the extended signature table was backwards, so we always ignored it. We should verify that the extended signature table fits within the total image size. Approved by: so Security: FreeBSD-EN-26:20.microcode Reviewed by: jrm, kib MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D57209 (cherry picked from commit 0beb172898499fff51eed4df3d9284cd1094afbb) (cherry picked from commit 38cbd2588f0b6f677f42287af425ac913da46294)
-rw-r--r--sys/x86/x86/ucode.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/sys/x86/x86/ucode.c b/sys/x86/x86/ucode.c
index 298ce5448853..9233e9fa93a8 100644
--- a/sys/x86/x86/ucode.c
+++ b/sys/x86/x86/ucode.c
@@ -179,7 +179,6 @@ ucode_intel_match(const uint8_t *data, size_t *len)
uint64_t platformid;
size_t resid;
uint32_t data_size, flags, regs[4], sig, total_size;
- int i;
do_cpuid(1, regs);
sig = regs[0];
@@ -201,19 +200,35 @@ ucode_intel_match(const uint8_t *data, size_t *len)
if (total_size == 0)
total_size = UCODE_INTEL_DEFAULT_DATA_SIZE +
sizeof(struct ucode_intel_header);
- if (data_size > total_size + sizeof(struct ucode_intel_header))
+
+ if (total_size > data_size + sizeof(struct ucode_intel_header))
table = (const struct ucode_intel_extsig_table *)
((const uint8_t *)(hdr + 1) + data_size);
else
table = NULL;
- if (hdr->processor_signature == sig) {
- if ((hdr->processor_flags & flags) != 0) {
- *len = data_size;
- return (hdr + 1);
+ if (hdr->processor_signature == sig &&
+ (hdr->processor_flags & flags) != 0) {
+ *len = data_size;
+ return (hdr + 1);
+ }
+ if (table != NULL) {
+ size_t extsize;
+
+ extsize = total_size -
+ (data_size + sizeof(struct ucode_intel_header));
+ if (extsize < sizeof(struct ucode_intel_extsig_table)) {
+ ucode_error = VERIFICATION_FAILED;
+ break;
}
- } else if (table != NULL) {
- for (i = 0; i < table->signature_count; i++) {
+ extsize -= sizeof(struct ucode_intel_extsig_table);
+ for (uint32_t i = 0; i < table->signature_count; i++) {
+ if (extsize < sizeof(struct ucode_intel_extsig)) {
+ ucode_error = VERIFICATION_FAILED;
+ goto out;
+ }
+ extsize -= sizeof(struct ucode_intel_extsig);
+
entry = &table->entries[i];
if (entry->processor_signature == sig &&
(entry->processor_flags & flags) != 0) {
@@ -223,6 +238,7 @@ ucode_intel_match(const uint8_t *data, size_t *len)
}
}
}
+out:
return (NULL);
}