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

From: tip-bot for Shu Wang
Date: Tue Jul 25 2017 - 09:54:17 EST


Commit-ID: a99f03428faa2e53cce17aec0d636de760ec281a
Gitweb: http://git.kernel.org/tip/a99f03428faa2e53cce17aec0d636de760ec281a
Author: Shu Wang <shuwang@xxxxxxxxxx>
AuthorDate: Mon, 24 Jul 2017 12:12:26 +0200
Committer: Ingo Molnar <mingo@xxxxxxxxxx>
CommitDate: Tue, 25 Jul 2017 11:26:19 +0200

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: Shu Wang <shuwang@xxxxxxxxxx>
[ Rewrite commit message. ]
Signed-off-by: Borislav Petkov <bp@xxxxxxx>
Cc: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
Cc: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
Cc: chuhu@xxxxxxxxxx
Cc: liwang@xxxxxxxxxx
Link: http://lkml.kernel.org/r/20170724101228.17326-2-bp@xxxxxxxxx
Signed-off-by: Ingo Molnar <mingo@xxxxxxxxxx>
---
arch/x86/kernel/cpu/microcode/amd.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c
index 21b1857..c6daec4 100644
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -400,9 +400,12 @@ static void update_cache(struct ucode_patch *new_patch)

list_for_each_entry(p, &microcode_cache, plist) {
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 */
+ kfree(new_patch->data);
+ kfree(new_patch);
return;
+ }

list_replace(&p->plist, &new_patch->plist);
kfree(p->data);