x86/microcode/AMD: Track patch allocation size explicitly
authorKees Cook <keescook@chromium.org>
Thu, 22 Sep 2022 03:10:10 +0000 (20:10 -0700)
committerBorislav Petkov <bp@suse.de>
Fri, 23 Sep 2022 11:46:26 +0000 (13:46 +0200)
In preparation for reducing the use of ksize(), record the actual
allocation size for later memcpy(). This avoids copying extra
(uninitialized!) bytes into the patch buffer when the requested
allocation size isn't exactly the size of a kmalloc bucket.
Additionally, fix potential future issues where runtime bounds checking
will notice that the buffer was allocated to a smaller value than
returned by ksize().

Fixes: 757885e94a22 ("x86, microcode, amd: Early microcode patch loading support for AMD")
Suggested-by: Daniel Micay <danielmicay@gmail.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Borislav Petkov <bp@suse.de>
Link: https://lore.kernel.org/lkml/CA+DvKQ+bp7Y7gmaVhacjv9uF6Ar-o4tet872h4Q8RPYPJjcJQA@mail.gmail.com/
arch/x86/include/asm/microcode.h
arch/x86/kernel/cpu/microcode/amd.c

index 7f7800e15ed01e7859047fe92d310b84f9777934..74ecc2bd6cd0f1ace97a9b5340d78d5b77893a94 100644 (file)
@@ -9,6 +9,7 @@
 struct ucode_patch {
        struct list_head plist;
        void *data;             /* Intel uses only this one */
+       unsigned int size;
        u32 patch_id;
        u16 equiv_cpu;
 };
index 5f38dd75cbc5e63a155f6114e8cbb537dbefe807..e7410e98fc1f9a55a57ab3f485beb584789df9b7 100644 (file)
@@ -788,6 +788,7 @@ static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover,
                kfree(patch);
                return -EINVAL;
        }
+       patch->size = *patch_size;
 
        mc_hdr      = (struct microcode_header_amd *)(fw + SECTION_HDR_SIZE);
        proc_id     = mc_hdr->processor_rev_id;
@@ -869,7 +870,7 @@ load_microcode_amd(bool save, u8 family, const u8 *data, size_t size)
                return ret;
 
        memset(amd_ucode_patch, 0, PATCH_MAX_SIZE);
-       memcpy(amd_ucode_patch, p->data, min_t(u32, ksize(p->data), PATCH_MAX_SIZE));
+       memcpy(amd_ucode_patch, p->data, min_t(u32, p->size, PATCH_MAX_SIZE));
 
        return ret;
 }