Skip to content

Commit 6e5cf31

Browse files
committed
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. Fixes: 019f34f ("x86, MCE, AMD: Move shared bank to node descriptor") Reported-by: Saar Amar <[email protected]> Reported-by: Dan Carpenter <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Cc: <[email protected]> Link: http://lkml.kernel.org/r/[email protected]
1 parent bb6d3fb commit 6e5cf31

File tree

1 file changed

+16
-17
lines changed
  • arch/x86/kernel/cpu/mce

1 file changed

+16
-17
lines changed

arch/x86/kernel/cpu/mce/amd.c

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

1201-
static int allocate_threshold_blocks(unsigned int cpu, unsigned int bank,
1202-
unsigned int block, u32 address)
1201+
static int allocate_threshold_blocks(unsigned int cpu, struct threshold_bank *tb,
1202+
unsigned int bank, unsigned int block,
1203+
u32 address)
12031204
{
12041205
struct threshold_block *b = NULL;
12051206
u32 low, high;
@@ -1243,24 +1244,20 @@ static int allocate_threshold_blocks(unsigned int cpu, unsigned int bank,
12431244

12441245
INIT_LIST_HEAD(&b->miscj);
12451246

1246-
if (per_cpu(threshold_banks, cpu)[bank]->blocks) {
1247-
list_add(&b->miscj,
1248-
&per_cpu(threshold_banks, cpu)[bank]->blocks->miscj);
1249-
} else {
1250-
per_cpu(threshold_banks, cpu)[bank]->blocks = b;
1251-
}
1247+
if (tb->blocks)
1248+
list_add(&b->miscj, &tb->blocks->miscj);
1249+
else
1250+
tb->blocks = b;
12521251

1253-
err = kobject_init_and_add(&b->kobj, &threshold_ktype,
1254-
per_cpu(threshold_banks, cpu)[bank]->kobj,
1255-
get_name(bank, b));
1252+
err = kobject_init_and_add(&b->kobj, &threshold_ktype, tb->kobj, get_name(bank, b));
12561253
if (err)
12571254
goto out_free;
12581255
recurse:
12591256
address = get_block_address(address, low, high, bank, ++block, cpu);
12601257
if (!address)
12611258
return 0;
12621259

1263-
err = allocate_threshold_blocks(cpu, bank, block, address);
1260+
err = allocate_threshold_blocks(cpu, tb, bank, block, address);
12641261
if (err)
12651262
goto out_free;
12661263

@@ -1345,8 +1342,6 @@ static int threshold_create_bank(unsigned int cpu, unsigned int bank)
13451342
goto out_free;
13461343
}
13471344

1348-
per_cpu(threshold_banks, cpu)[bank] = b;
1349-
13501345
if (is_shared_bank(bank)) {
13511346
refcount_set(&b->cpus, 1);
13521347

@@ -1357,9 +1352,13 @@ static int threshold_create_bank(unsigned int cpu, unsigned int bank)
13571352
}
13581353
}
13591354

1360-
err = allocate_threshold_blocks(cpu, bank, 0, msr_ops.misc(bank));
1361-
if (!err)
1362-
goto out;
1355+
err = allocate_threshold_blocks(cpu, b, bank, 0, msr_ops.misc(bank));
1356+
if (err)
1357+
goto out_free;
1358+
1359+
per_cpu(threshold_banks, cpu)[bank] = b;
1360+
1361+
return 0;
13631362

13641363
out_free:
13651364
kfree(b);

0 commit comments

Comments
 (0)