FAILED: patch "[PATCH] x86/mce/amd: Publish the bank pointer only after setup has" failed to apply to 4.4-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 4.4-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 6e5cf31fbe651bed7ba1df768f2e123531132417 Mon Sep 17 00:00:00 2001
From: Borislav Petkov <[email protected]>
Date: Tue, 4 Feb 2020 13:28:41 +0100
Subject: [PATCH] x86/mce/amd: Publish the bank pointer only after setup has
succeeded
threshold_create_bank() creates a bank descriptor per MCA error thresholding counter which can be controlled over sysfs. It publishes the pointer to that bank in a per-CPU variable and then goes on to create additional thresholding blocks if the bank has such.
However, that creation of additional blocks in allocate_threshold_blocks() can fail, leading to a use-after-free through the per-CPU pointer.
Therefore, publish that pointer only after all blocks have been setup successfully.
arch/x86/kernel/cpu/mce/amd.c +16 -17
@@ -1198,8 +1198,9 @@ static const char *get_name(unsigned int bank, struct threshold_block *b)return buf_mcatype; } -static int allocate_threshold_blocks (unsigned int cpu,unsigned int bank, -unsigned int block,u32 address) +static int allocate_threshold_blocks (unsigned int cpu,struct threshold_bank *tb, +unsigned int bank,unsigned int block, +u32 address) {struct threshold_block *b =NULL ;u32 low, high;
@@ -1243,16 +1244,12 @@ static int allocate_threshold_blocks(unsigned int cpu, unsigned int bank,INIT_LIST_HEAD (&b->miscj); -if (per_cpu (threshold_banks, cpu)[bank]->blocks) { -list_add (&b->miscj, - &per_cpu (threshold_banks, cpu)[bank]->blocks->miscj); - }else { -per_cpu (threshold_banks, cpu)[bank]->blocks = b; - } +if (tb->blocks) +list_add (&b->miscj, &tb->blocks->miscj); +else + tb->blocks = b; - err =kobject_init_and_add (&b->kobj, &threshold_ktype, -per_cpu (threshold_banks, cpu)[bank]->kobj, -get_name (bank, b)); + err =kobject_init_and_add (&b->kobj, &threshold_ktype, tb->kobj,get_name (bank, b));if (err) goto out_free; recurse:
@@ -1260,7 +1257,7 @@ static int allocate_threshold_blocks(unsigned int cpu, unsigned int bank,if (!address)return 0 ; - err =allocate_threshold_blocks (cpu, bank, block, address); + err =allocate_threshold_blocks (cpu, tb, bank, block, address);if (err) goto out_free;
@@ -1345,8 +1342,6 @@ static int threshold_create_bank(unsigned int cpu, unsigned int bank) goto out_free; } -per_cpu (threshold_banks, cpu)[bank] = b; -if (is_shared_bank (bank)) {refcount_set (&b->cpus,1 );
@@ -1357,9 +1352,13 @@ static int threshold_create_bank(unsigned int cpu, unsigned int bank) } } - err =allocate_threshold_blocks (cpu, bank,0 , msr_ops.misc (bank)); -if (!err) - goto out; + err =allocate_threshold_blocks (cpu, b, bank,0 , msr_ops.misc (bank)); +if (err) + goto out_free; + +per_cpu (threshold_banks, cpu)[bank] = b; + +return 0 ; out_free:kfree (b);