@@ -303,11 +303,20 @@ static int get_ucode_from_buffer_amd(
static int install_equiv_cpu_table(
struct microcode_amd *mc_amd,
const void *data,
+ size_t size_left,
size_t *offset)
{
- const struct mpbhdr *mpbuf = data + *offset + 4;
+ const struct mpbhdr *mpbuf;
const struct equiv_cpu_entry *eq;
+ if ( size_left < (sizeof(*mpbuf) + 4) ||
+ (mpbuf = data + *offset + 4,
+ size_left - sizeof(*mpbuf) - 4 < mpbuf->len) )
+ {
+ printk(XENLOG_WARNING "microcode: No space for equivalent cpu table\n");
+ return -EINVAL;
+ }
+
*offset += mpbuf->len + CONT_HDR_SIZE; /* add header length */
if ( mpbuf->type != UCODE_EQUIV_CPU_TABLE_TYPE )
@@ -417,7 +426,8 @@ static struct microcode_patch *cpu_request_microcode(const void *buf,
current_cpu_id = cpuid_eax(0x00000001);
- if ( *(const uint32_t *)buf != UCODE_MAGIC )
+ if ( bufsize < 4 ||
+ *(const uint32_t *)buf != UCODE_MAGIC )
{
printk(KERN_ERR "microcode: Wrong microcode patch file magic\n");
error = -EINVAL;
@@ -447,24 +457,13 @@ static struct microcode_patch *cpu_request_microcode(const void *buf,
*/
while ( offset < bufsize )
{
- error = install_equiv_cpu_table(mc_amd, buf, &offset);
+ error = install_equiv_cpu_table(mc_amd, buf, bufsize - offset, &offset);
if ( error )
{
printk(KERN_ERR "microcode: installing equivalent cpu table failed\n");
break;
}
- /*
- * Could happen as we advance 'offset' early
- * in install_equiv_cpu_table
- */
- if ( offset > bufsize )
- {
- printk(KERN_ERR "microcode: Microcode buffer overrun\n");
- error = -EINVAL;
- break;
- }
-
if ( find_equiv_cpu_id(mc_amd->equiv_cpu_table, current_cpu_id,
&equiv_cpu_id) )
break;