@bp is a local variable, calling mce_threshold_remove_device() when threshold_create_bank() fails will not free the @bp. Note that mce_threshold_remove_device() frees the @bp only if it's already stored in the @threshold_banks per-CPU variable. At that point, the @threshold_banks per-CPU variable is still NULL, so the mce_threshold_remove_device() will just be a no-op and the @bp is leaked. Fix this by storing @bp to @threshold_banks before the loop, so in case we fail, mce_threshold_remove_device() will free the @bp. This bug is introduced by commit 6458de97fc15530b544 ("x86/mce/amd: Straighten CPU hotplug path") [1]. Link: https://lore.kernel.org/all/20200403161943.1458-6-bp@xxxxxxxxx [1] v3: - Fold in changes from Alviro, the previous version is still leaking @bank[n]. v2: - No changes. Cc: Borislav Petkov <bp@xxxxxxxxx> Cc: Dave Hansen <dave.hansen@xxxxxxxxxxxxxxx> Cc: "H. Peter Anvin" <hpa@xxxxxxxxx> Cc: Ingo Molnar <mingo@xxxxxxxxxx> Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx> Cc: Tony Luck <tony.luck@xxxxxxxxx> Fixes: 6458de97fc15530b54477c4e2b70af653e8ac3d9 ("x86/mce/amd: Straighten CPU hotplug path") Cc: stable@xxxxxxxxxxxxxxx # v5.8+ Co-authored-by: Alviro Iskandar Setiawan <alviro.iskandar@xxxxxxxxxxx> Signed-off-by: Alviro Iskandar Setiawan <alviro.iskandar@xxxxxxxxxxx> Signed-off-by: Ammar Faizi <ammarfaizi2@xxxxxxxxxxx> --- arch/x86/kernel/cpu/mce/amd.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/cpu/mce/amd.c b/arch/x86/kernel/cpu/mce/amd.c index 9f4b508886dd..a5ef161facd9 100644 --- a/arch/x86/kernel/cpu/mce/amd.c +++ b/arch/x86/kernel/cpu/mce/amd.c @@ -1346,19 +1346,23 @@ int mce_threshold_create_device(unsigned int cpu) if (!bp) return -ENOMEM; + /* + * If we fail, mce_threshold_remove_device() will free the @bp + * via @threshold_banks. + */ + this_cpu_write(threshold_banks, bp); + for (bank = 0; bank < numbanks; ++bank) { if (!(this_cpu_read(bank_map) & (1 << bank))) continue; err = threshold_create_bank(bp, cpu, bank); - if (err) - goto out_err; + if (err) { + mce_threshold_remove_device(cpu); + return err; + } } - this_cpu_write(threshold_banks, bp); if (thresholding_irq_en) mce_threshold_vector = amd_threshold_interrupt; return 0; -out_err: - mce_threshold_remove_device(cpu); - return err; } -- 2.32.0