Commit ffef67b
mm/memory: fix PMD/PUD checks in follow_pfnmap_start()
follow_pfnmap_start() suffers from two problems:
(1) We are not re-fetching the pmd/pud after taking the PTL
Therefore, we are not properly stabilizing what the lock actually
protects. If there is concurrent zapping, we would indicate to the
caller that we found an entry, however, that entry might already have
been invalidated, or contain a different PFN after taking the lock.
Properly use pmdp_get() / pudp_get() after taking the lock.
(2) pmd_leaf() / pud_leaf() are not well defined on non-present entries
pmd_leaf()/pud_leaf() could wrongly trigger on non-present entries.
There is no real guarantee that pmd_leaf()/pud_leaf() returns something
reasonable on non-present entries. Most architectures indeed either
perform a present check or make it work by smart use of flags.
However, for example loongarch checks the _PAGE_HUGE flag in pmd_leaf(),
and always sets the _PAGE_HUGE flag in __swp_entry_to_pmd(). Whereby
pmd_trans_huge() explicitly checks pmd_present(), pmd_leaf() does not do
that.
Let's check pmd_present()/pud_present() before assuming "the is a present
PMD leaf" when spotting pmd_leaf()/pud_leaf(), like other page table
handling code that traverses user page tables does.
Given that non-present PMD entries are likely rare in VM_IO|VM_PFNMAP, (1)
is likely more relevant than (2). It is questionable how often (1) would
actually trigger, but let's CC stable to be sure.
This was found by code inspection.
Link: https://lkml.kernel.org/r/[email protected]
Fixes: 6da8e96 ("mm: new follow_pfnmap API")
Signed-off-by: David Hildenbrand (Arm) <[email protected]>
Acked-by: Mike Rapoport (Microsoft) <[email protected]>
Reviewed-by: Lorenzo Stoakes (Oracle) <[email protected]>
Cc: Liam Howlett <[email protected]>
Cc: Michal Hocko <[email protected]>
Cc: Peter Xu <[email protected]>
Cc: Suren Baghdasaryan <[email protected]>
Cc: Vlastimil Babka <[email protected]>
Cc: <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>1 parent 6557004 commit ffef67b
1 file changed
Lines changed: 15 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6815 | 6815 | | |
6816 | 6816 | | |
6817 | 6817 | | |
6818 | | - | |
| 6818 | + | |
6819 | 6819 | | |
6820 | 6820 | | |
6821 | 6821 | | |
6822 | | - | |
| 6822 | + | |
| 6823 | + | |
| 6824 | + | |
| 6825 | + | |
| 6826 | + | |
| 6827 | + | |
6823 | 6828 | | |
6824 | 6829 | | |
6825 | 6830 | | |
| |||
6831 | 6836 | | |
6832 | 6837 | | |
6833 | 6838 | | |
| 6839 | + | |
| 6840 | + | |
6834 | 6841 | | |
6835 | 6842 | | |
6836 | | - | |
| 6843 | + | |
| 6844 | + | |
| 6845 | + | |
| 6846 | + | |
| 6847 | + | |
| 6848 | + | |
6837 | 6849 | | |
6838 | 6850 | | |
6839 | 6851 | | |
| |||
0 commit comments