Skip to content

Commit 10be332

Browse files
suryasaimadhugregkh
authored andcommitted
x86/mce/amd: Publish the bank pointer only after setup has succeeded
commit 6e5cf31 upstream. 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. Fixes: 019f34f ("x86, MCE, AMD: Move shared bank to node descriptor") Reported-by: Saar Amar <Saar.Amar@microsoft.com> Reported-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Borislav Petkov <bp@suse.de> Cc: <stable@vger.kernel.org> Link: http://lkml.kernel.org/r/20200128140846.phctkvx5btiexvbx@kili.mountain Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 3404ad4 commit 10be332

1 file changed

Lines changed: 16 additions & 17 deletions

File tree

arch/x86/kernel/cpu/mcheck/mce_amd.c

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -879,8 +879,9 @@ static const char *get_name(unsigned int bank, struct threshold_block *b)
879879
return buf_mcatype;
880880
}
881881

882-
static int allocate_threshold_blocks(unsigned int cpu, unsigned int bank,
883-
unsigned int block, u32 address)
882+
static int allocate_threshold_blocks(unsigned int cpu, struct threshold_bank *tb,
883+
unsigned int bank, unsigned int block,
884+
u32 address)
884885
{
885886
struct threshold_block *b = NULL;
886887
u32 low, high;
@@ -924,24 +925,20 @@ static int allocate_threshold_blocks(unsigned int cpu, unsigned int bank,
924925

925926
INIT_LIST_HEAD(&b->miscj);
926927

927-
if (per_cpu(threshold_banks, cpu)[bank]->blocks) {
928-
list_add(&b->miscj,
929-
&per_cpu(threshold_banks, cpu)[bank]->blocks->miscj);
930-
} else {
931-
per_cpu(threshold_banks, cpu)[bank]->blocks = b;
932-
}
928+
if (tb->blocks)
929+
list_add(&b->miscj, &tb->blocks->miscj);
930+
else
931+
tb->blocks = b;
933932

934-
err = kobject_init_and_add(&b->kobj, &threshold_ktype,
935-
per_cpu(threshold_banks, cpu)[bank]->kobj,
936-
get_name(bank, b));
933+
err = kobject_init_and_add(&b->kobj, &threshold_ktype, tb->kobj, get_name(bank, b));
937934
if (err)
938935
goto out_free;
939936
recurse:
940937
address = get_block_address(cpu, address, low, high, bank, ++block);
941938
if (!address)
942939
return 0;
943940

944-
err = allocate_threshold_blocks(cpu, bank, block, address);
941+
err = allocate_threshold_blocks(cpu, tb, bank, block, address);
945942
if (err)
946943
goto out_free;
947944

@@ -1026,8 +1023,6 @@ static int threshold_create_bank(unsigned int cpu, unsigned int bank)
10261023
goto out_free;
10271024
}
10281025

1029-
per_cpu(threshold_banks, cpu)[bank] = b;
1030-
10311026
if (is_shared_bank(bank)) {
10321027
atomic_set(&b->cpus, 1);
10331028

@@ -1038,9 +1033,13 @@ static int threshold_create_bank(unsigned int cpu, unsigned int bank)
10381033
}
10391034
}
10401035

1041-
err = allocate_threshold_blocks(cpu, bank, 0, msr_ops.misc(bank));
1042-
if (!err)
1043-
goto out;
1036+
err = allocate_threshold_blocks(cpu, b, bank, 0, msr_ops.misc(bank));
1037+
if (err)
1038+
goto out_free;
1039+
1040+
per_cpu(threshold_banks, cpu)[bank] = b;
1041+
1042+
return 0;
10441043

10451044
out_free:
10461045
kfree(b);

0 commit comments

Comments
 (0)