diff options
| author | Huang Ying <[email protected]> | 2018-06-08 00:06:34 +0000 |
|---|---|---|
| committer | Linus Torvalds <[email protected]> | 2018-06-08 00:34:35 +0000 |
| commit | 688272809fcce5b17fcefd5892b59f3788efb144 (patch) | |
| tree | 4f77743f058101bbde54ba77261984379c8ba822 /mm/sparse.c | |
| parent | mm/docs: describe memory.low refinements (diff) | |
| download | kernel-688272809fcce5b17fcefd5892b59f3788efb144.tar.gz kernel-688272809fcce5b17fcefd5892b59f3788efb144.zip | |
mm, gup: prevent pmd checking race in follow_pmd_mask()
mmap_sem will be read locked when calling follow_pmd_mask(). But this
cannot prevent PMD from being changed for all cases when PTL is
unlocked, for example, from pmd_trans_huge() to pmd_none() via
MADV_DONTNEED. So it is possible for the pmd_present() check in
follow_pmd_mask() to encounter an invalid PMD. This may cause an
incorrect VM_BUG_ON() or an infinite loop. Fix this by reading the PMD
entry into a local variable with READ_ONCE() and checking the local
variable and pmd_none() in the retry loop.
As Kirill pointed out, with PTL unlocked, the *pmd may be changed under
us, so reading it directly again and again may incur weird bugs. So
although using *pmd directly other than for pmd_present() checking may
be safe, it is still better to replace them to read *pmd once and check
the local variable multiple times.
When PTL unlocked, replace all *pmd with local variable was suggested by
Kirill.
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: "Huang, Ying" <[email protected]>
Reviewed-by: Zi Yan <[email protected]>
Cc: "Kirill A. Shutemov" <[email protected]>
Cc: Al Viro <[email protected]>
Cc: "Aneesh Kumar K.V" <[email protected]>
Cc: Dan Williams <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Diffstat (limited to 'mm/sparse.c')
0 files changed, 0 insertions, 0 deletions
