Skip to content

Commit 49c473e

Browse files
kvaneeshgregkh
authored andcommitted
powerpc/radix: Fix kernel crash with mremap()
commit 579b923 upstream. With support for split pmd lock, we use pmd page pmd_huge_pte pointer to store the deposited page table. In those config when we move page tables we need to make sure we move the deposited page table to the correct pmd page. Otherwise this can result in crash when we withdraw of deposited page table because we can find the pmd_huge_pte NULL. eg: __split_huge_pmd+0x1070/0x1940 __split_huge_pmd+0xe34/0x1940 (unreliable) vma_adjust_trans_huge+0x110/0x1c0 __vma_adjust+0x2b4/0x9b0 __split_vma+0x1b8/0x280 __do_munmap+0x13c/0x550 sys_mremap+0x220/0x7e0 system_call+0x5c/0x70 Fixes: 675d995 ("powerpc/book3s64: Enable split pmd ptlock.") Cc: [email protected] # v4.18+ Signed-off-by: Aneesh Kumar K.V <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent d4e7c94 commit 49c473e

File tree

2 files changed

+29
-15
lines changed

2 files changed

+29
-15
lines changed

arch/powerpc/include/asm/book3s/64/pgtable.h

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,21 +1234,13 @@ extern pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
12341234

12351235
#define pmd_move_must_withdraw pmd_move_must_withdraw
12361236
struct spinlock;
1237-
static inline int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl,
1238-
struct spinlock *old_pmd_ptl,
1239-
struct vm_area_struct *vma)
1240-
{
1241-
if (radix_enabled())
1242-
return false;
1243-
/*
1244-
* Archs like ppc64 use pgtable to store per pmd
1245-
* specific information. So when we switch the pmd,
1246-
* we should also withdraw and deposit the pgtable
1247-
*/
1248-
return true;
1249-
}
1250-
1251-
1237+
extern int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl,
1238+
struct spinlock *old_pmd_ptl,
1239+
struct vm_area_struct *vma);
1240+
/*
1241+
* Hash translation mode use the deposited table to store hash pte
1242+
* slot information.
1243+
*/
12521244
#define arch_needs_pgtable_deposit arch_needs_pgtable_deposit
12531245
static inline bool arch_needs_pgtable_deposit(void)
12541246
{

arch/powerpc/mm/pgtable-book3s64.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,3 +477,25 @@ void arch_report_meminfo(struct seq_file *m)
477477
atomic_long_read(&direct_pages_count[MMU_PAGE_1G]) << 20);
478478
}
479479
#endif /* CONFIG_PROC_FS */
480+
481+
/*
482+
* For hash translation mode, we use the deposited table to store hash slot
483+
* information and they are stored at PTRS_PER_PMD offset from related pmd
484+
* location. Hence a pmd move requires deposit and withdraw.
485+
*
486+
* For radix translation with split pmd ptl, we store the deposited table in the
487+
* pmd page. Hence if we have different pmd page we need to withdraw during pmd
488+
* move.
489+
*
490+
* With hash we use deposited table always irrespective of anon or not.
491+
* With radix we use deposited table only for anonymous mapping.
492+
*/
493+
int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl,
494+
struct spinlock *old_pmd_ptl,
495+
struct vm_area_struct *vma)
496+
{
497+
if (radix_enabled())
498+
return (new_pmd_ptl != old_pmd_ptl) && vma_is_anonymous(vma);
499+
500+
return true;
501+
}

0 commit comments

Comments
 (0)