From: Nicholas Piggin <npiggin@gmail.com> Date: 2019-06-03 06:07:14
Commit 1b2443a547f9 ("powerpc/book3s64: Avoid multiple endian conversion
in pte helpers") changed the actual bitwise tests in pte_access_permitted
by using pte_write() and pte_present() helpers rather than raw bitwise
testing _PAGE_WRITE and _PAGE_PRESENT bits.
The pte_present change now returns true for ptes which are !_PAGE_PRESENT
and _PAGE_INVALID, which is the combination used by pmdp_invalidate to
synchronize access from lock-free lookups. pte_access_permitted is used by
pmd_access_permitted, so allowing GUP lock free access to proceed with
such PTEs breaks this synchronisation.
This bug has been observed on HPT host, with random crashes and corruption
in guests, usually together with bad PMD messages in the host.
Fix this by adding an explicit check in pmd_access_permitted, and
documenting the condition explicitly.
The pte_write() change should be okay, and would prevent GUP from falling
back to the slow path when encountering savedwrite ptes, which matches
what x86 (that does not implement savedwrite) does.
Fixes: 1b2443a547f9 ("powerpc/book3s64: Avoid multiple endian conversion in pte helpers")
Cc: Aneesh Kumar K.V <redacted>
Cc: Christophe Leroy <redacted>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/include/asm/book3s/64/pgtable.h | 19 ++++++++++++++++++-
arch/powerpc/mm/book3s64/pgtable.c | 3 +++
2 files changed, 21 insertions(+), 1 deletion(-)
Commit 1b2443a547f9 ("powerpc/book3s64: Avoid multiple endian conversion
in pte helpers") changed the actual bitwise tests in pte_access_permitted
by using pte_write() and pte_present() helpers rather than raw bitwise
testing _PAGE_WRITE and _PAGE_PRESENT bits.
The pte_present change now returns true for ptes which are !_PAGE_PRESENT
and _PAGE_INVALID, which is the combination used by pmdp_invalidate to
synchronize access from lock-free lookups. pte_access_permitted is used by
pmd_access_permitted, so allowing GUP lock free access to proceed with
such PTEs breaks this synchronisation.
This bug has been observed on HPT host, with random crashes and corruption
in guests, usually together with bad PMD messages in the host.
Fix this by adding an explicit check in pmd_access_permitted, and
documenting the condition explicitly.
The pte_write() change should be okay, and would prevent GUP from falling
back to the slow path when encountering savedwrite ptes, which matches
what x86 (that does not implement savedwrite) does.
Fixes: 1b2443a547f9 ("powerpc/book3s64: Avoid multiple endian conversion in pte helpers")
Cc: Aneesh Kumar K.V <redacted>
Cc: Christophe Leroy <redacted>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/include/asm/book3s/64/pgtable.h | 19 ++++++++++++++++++-
arch/powerpc/mm/book3s64/pgtable.c | 3 +++
2 files changed, 21 insertions(+), 1 deletion(-)
From: Nicholas Piggin <npiggin@gmail.com> Date: 2019-06-03 07:35:29
Aneesh Kumar K.V's on June 3, 2019 4:43 pm:
On 6/3/19 11:35 AM, Nicholas Piggin wrote:
quoted
Commit 1b2443a547f9 ("powerpc/book3s64: Avoid multiple endian conversion
in pte helpers") changed the actual bitwise tests in pte_access_permitted
by using pte_write() and pte_present() helpers rather than raw bitwise
testing _PAGE_WRITE and _PAGE_PRESENT bits.
The pte_present change now returns true for ptes which are !_PAGE_PRESENT
and _PAGE_INVALID, which is the combination used by pmdp_invalidate to
synchronize access from lock-free lookups. pte_access_permitted is used by
pmd_access_permitted, so allowing GUP lock free access to proceed with
such PTEs breaks this synchronisation.
This bug has been observed on HPT host, with random crashes and corruption
in guests, usually together with bad PMD messages in the host.
Fix this by adding an explicit check in pmd_access_permitted, and
documenting the condition explicitly.
The pte_write() change should be okay, and would prevent GUP from falling
back to the slow path when encountering savedwrite ptes, which matches
what x86 (that does not implement savedwrite) does.
Fixes: 1b2443a547f9 ("powerpc/book3s64: Avoid multiple endian conversion in pte helpers")
Cc: Aneesh Kumar K.V <redacted>
Cc: Christophe Leroy <redacted>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/include/asm/book3s/64/pgtable.h | 19 ++++++++++++++++++-
arch/powerpc/mm/book3s64/pgtable.c | 3 +++
2 files changed, 21 insertions(+), 1 deletion(-)
you need to do similar for other lockless page table walk like
find_linux_pte
Yeah good point as discussed offline. I was going to make that a
separate patch, it would have a different Fixes:. I have not been
able to trigger any bugs caused by it, whereas the bug caused by
this patch hits reliably in about 10 minutes or less.
Maybe the race window is just a lot smaller or the function is
less frequently used?
Thanks,
Nick
Commit 1b2443a547f9 ("powerpc/book3s64: Avoid multiple endian conversion
in pte helpers") changed the actual bitwise tests in pte_access_permitted
by using pte_write() and pte_present() helpers rather than raw bitwise
testing _PAGE_WRITE and _PAGE_PRESENT bits.
The pte_present change now returns true for ptes which are !_PAGE_PRESENT
and _PAGE_INVALID, which is the combination used by pmdp_invalidate to
synchronize access from lock-free lookups. pte_access_permitted is used by
pmd_access_permitted, so allowing GUP lock free access to proceed with
such PTEs breaks this synchronisation.
This bug has been observed on HPT host, with random crashes and corruption
in guests, usually together with bad PMD messages in the host.
Fix this by adding an explicit check in pmd_access_permitted, and
documenting the condition explicitly.
The pte_write() change should be okay, and would prevent GUP from falling
back to the slow path when encountering savedwrite ptes, which matches
what x86 (that does not implement savedwrite) does.
I guess we are doing the find_linux_pte change in another patch.
Reviewed-by: Aneesh Kumar K.V <redacted>
From: Nicholas Piggin <npiggin@gmail.com> Date: 2019-06-07 04:11:01
Aneesh Kumar K.V's on June 7, 2019 1:23 am:
Nicholas Piggin [off-list ref] writes:
quoted
Commit 1b2443a547f9 ("powerpc/book3s64: Avoid multiple endian conversion
in pte helpers") changed the actual bitwise tests in pte_access_permitted
by using pte_write() and pte_present() helpers rather than raw bitwise
testing _PAGE_WRITE and _PAGE_PRESENT bits.
The pte_present change now returns true for ptes which are !_PAGE_PRESENT
and _PAGE_INVALID, which is the combination used by pmdp_invalidate to
synchronize access from lock-free lookups. pte_access_permitted is used by
pmd_access_permitted, so allowing GUP lock free access to proceed with
such PTEs breaks this synchronisation.
This bug has been observed on HPT host, with random crashes and corruption
in guests, usually together with bad PMD messages in the host.
Fix this by adding an explicit check in pmd_access_permitted, and
documenting the condition explicitly.
The pte_write() change should be okay, and would prevent GUP from falling
back to the slow path when encountering savedwrite ptes, which matches
what x86 (that does not implement savedwrite) does.
I guess we are doing the find_linux_pte change in another patch.
Reviewed-by: Aneesh Kumar K.V <redacted>
Sorry, just got delayed with re-testing. Thanks for the feedback on it
I send new patches.
Two patches yes because they fix issues introduced in different
commits so it should make backports easier.
Thanks,
Nick