Commit a99f0342 authored by Shu Wang's avatar Shu Wang Committed by Ingo Molnar

x86/microcode/AMD: Free unneeded patch before exit from update_cache()

verify_and_add_patch() allocates memory for a microcode patch and hands
it down to be added to the cache of patches. However, if the cache
already has the latest patch, the newly allocated one needs to be freed
before returning. Do that.

This issue has been found by kmemleak:

  unreferenced object 0xffff88010e780b40 (size 32):
    comm "bash", pid 860, jiffies 4294690939 (age 29.297s)
    backtrace:
       kmemleak_alloc
       kmem_cache_alloc_trace
       load_microcode_amd.isra.0
       request_microcode_amd
       reload_store
       dev_attr_store
       sysfs_kf_write
       kernfs_fop_write
       __vfs_write
       vfs_write
       SyS_write
       do_syscall_64
       return_from_SYSCALL_64
       0xffffffffffffffff

  (gdb) list *0xffffffff81050d60
  0xffffffff81050d60 is in load_microcode_amd
                (arch/x86/kernel/cpu/microcode/amd.c:616).

which is this:

	patch = kzalloc(sizeof(*patch), GFP_KERNEL);
-->	if (!patch) {
		pr_err("Patch allocation failure.\n");
		return -EINVAL;
	}
Signed-off-by: default avatarShu Wang <shuwang@redhat.com>
[ Rewrite commit message. ]
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: chuhu@redhat.com
Cc: liwang@redhat.com
Link: http://lkml.kernel.org/r/20170724101228.17326-2-bp@alien8.deSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent 520eccdf
...@@ -400,9 +400,12 @@ static void update_cache(struct ucode_patch *new_patch) ...@@ -400,9 +400,12 @@ static void update_cache(struct ucode_patch *new_patch)
list_for_each_entry(p, &microcode_cache, plist) { list_for_each_entry(p, &microcode_cache, plist) {
if (p->equiv_cpu == new_patch->equiv_cpu) { if (p->equiv_cpu == new_patch->equiv_cpu) {
if (p->patch_id >= new_patch->patch_id) if (p->patch_id >= new_patch->patch_id) {
/* we already have the latest patch */ /* we already have the latest patch */
kfree(new_patch->data);
kfree(new_patch);
return; return;
}
list_replace(&p->plist, &new_patch->plist); list_replace(&p->plist, &new_patch->plist);
kfree(p->data); kfree(p->data);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment