Skip to content

Commit 51c3c62

Browse files
mikeympe
authored andcommitted
powerpc: Avoid code patching freed init sections
This stops us from doing code patching in init sections after they've been freed. In this chain: kvm_guest_init() -> kvm_use_magic_page() -> fault_in_pages_readable() -> __get_user() -> __get_user_nocheck() -> barrier_nospec(); We have a code patching location at barrier_nospec() and kvm_guest_init() is an init function. This whole chain gets inlined, so when we free the init section (hence kvm_guest_init()), this code goes away and hence should no longer be patched. We seen this as userspace memory corruption when using a memory checker while doing partition migration testing on powervm (this starts the code patching post migration via /sys/kernel/mobility/migration). In theory, it could also happen when using /sys/kernel/debug/powerpc/barrier_nospec. Cc: stable@vger.kernel.org # 4.13+ Signed-off-by: Michael Neuling <mikey@neuling.org> Reviewed-by: Nicholas Piggin <npiggin@gmail.com> Reviewed-by: Christophe Leroy <christophe.leroy@c-s.fr> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
1 parent f14040b commit 51c3c62

File tree

3 files changed

+9
-0
lines changed

3 files changed

+9
-0
lines changed

arch/powerpc/include/asm/setup.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ extern void ppc_printk_progress(char *s, unsigned short hex);
99

1010
extern unsigned int rtas_data;
1111
extern unsigned long long memory_limit;
12+
extern bool init_mem_is_free;
1213
extern unsigned long klimit;
1314
extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask);
1415

arch/powerpc/lib/code-patching.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ static int __patch_instruction(unsigned int *exec_addr, unsigned int instr,
2828
{
2929
int err;
3030

31+
/* Make sure we aren't patching a freed init section */
32+
if (init_mem_is_free && init_section_contains(exec_addr, 4)) {
33+
pr_debug("Skipping init section patching addr: 0x%px\n", exec_addr);
34+
return 0;
35+
}
36+
3137
__put_user_size(instr, patch_addr, 4, err);
3238
if (err)
3339
return err;

arch/powerpc/mm/mem.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
#endif
6464

6565
unsigned long long memory_limit;
66+
bool init_mem_is_free;
6667

6768
#ifdef CONFIG_HIGHMEM
6869
pte_t *kmap_pte;
@@ -396,6 +397,7 @@ void free_initmem(void)
396397
{
397398
ppc_md.progress = ppc_printk_progress;
398399
mark_initmem_nx();
400+
init_mem_is_free = true;
399401
free_initmem_default(POISON_FREE_INITMEM);
400402
}
401403

0 commit comments

Comments
 (0)