Re: [PATCH V2] mm/powerpc: Fix _PAGE_PTE breaking swapoff
On Mon, 2016-01-11 at 21:19 +0530, Aneesh Kumar K.V wrote: > Core kernel expect swp_entry_t to be consisting of > only swap type and swap offset. We should not leak pte bits to > swp_entry_t. This breaks swapoff which use the swap type and offset > to build a swp_entry_t and later compare that to the swp_entry_t > obtained from linux page table pte. Leaking pte bits to swp_entry_t > breaks that comparison and results in us looping in try_to_unuse. > > The stack trace can be anywhere below try_to_unuse() in mm/swapfile.c, > since swapoff is circling around and around that function, reading from > each used swap block into a page, then trying to find where that page > belongs, looking at every non-file pte of every mm that ever swapped. > > Reported-by: Hugh Dickins> Suggested-by: Hugh Dickins > Signed-off-by: Aneesh Kumar K.V Thanks. I slightly edited the wording in the change log and added: Fixes: 6a119eae942c ("powerpc/mm: Add a _PAGE_PTE bit") cheers ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH V2] mm/powerpc: Fix _PAGE_PTE breaking swapoff
Core kernel expect swp_entry_t to be consisting of only swap type and swap offset. We should not leak pte bits to swp_entry_t. This breaks swapoff which use the swap type and offset to build a swp_entry_t and later compare that to the swp_entry_t obtained from linux page table pte. Leaking pte bits to swp_entry_t breaks that comparison and results in us looping in try_to_unuse. The stack trace can be anywhere below try_to_unuse() in mm/swapfile.c, since swapoff is circling around and around that function, reading from each used swap block into a page, then trying to find where that page belongs, looking at every non-file pte of every mm that ever swapped. Reported-by: Hugh DickinsSuggested-by: Hugh Dickins Signed-off-by: Aneesh Kumar K.V --- Changes from V1: * improve change log and code comment arch/powerpc/include/asm/book3s/64/pgtable.h | 11 --- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h index 03c1a5a21c0c..cecb971674a8 100644 --- a/arch/powerpc/include/asm/book3s/64/pgtable.h +++ b/arch/powerpc/include/asm/book3s/64/pgtable.h @@ -158,9 +158,14 @@ static inline void pgd_set(pgd_t *pgdp, unsigned long val) #define __swp_entry(type, offset) ((swp_entry_t) { \ ((type) << _PAGE_BIT_SWAP_TYPE) \ | ((offset) << PTE_RPN_SHIFT) }) - -#define __pte_to_swp_entry(pte)((swp_entry_t) { pte_val((pte)) }) -#define __swp_entry_to_pte(x) __pte((x).val) +/* + * swp_entry_t should be independent of pte bits. We build a swp_entry_t from + * swap type and offset we get from swap and convert that to pte to + * find a matching pte in linux page table. + * Clear bits not found in swap entries here + */ +#define __pte_to_swp_entry(pte)((swp_entry_t) { pte_val((pte)) & ~_PAGE_PTE }) +#define __swp_entry_to_pte(x) __pte((x).val | _PAGE_PTE) #ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY #define _PAGE_SWP_SOFT_DIRTY (1UL << (SWP_TYPE_BITS + _PAGE_BIT_SWAP_TYPE)) -- 2.5.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH V2] mm/powerpc: Fix _PAGE_PTE breaking swapoff
On Mon, 11 Jan 2016, Aneesh Kumar K.V wrote: > Core kernel expect swp_entry_t to be consisting of > only swap type and swap offset. We should not leak pte bits to > swp_entry_t. This breaks swapoff which use the swap type and offset > to build a swp_entry_t and later compare that to the swp_entry_t > obtained from linux page table pte. Leaking pte bits to swp_entry_t > breaks that comparison and results in us looping in try_to_unuse. > > The stack trace can be anywhere below try_to_unuse() in mm/swapfile.c, > since swapoff is circling around and around that function, reading from > each used swap block into a page, then trying to find where that page > belongs, looking at every non-file pte of every mm that ever swapped. > > Reported-by: Hugh Dickins> Suggested-by: Hugh Dickins > Signed-off-by: Aneesh Kumar K.V I think we've seen enough of my name above, but if it helps further Acked-by: Hugh Dickins Though I don't find the code comment below on swp_entry_t enlightening - your commit description above is much more helpful. If I were writing it, I might say... hmm, it's too hard: given all the convolutions, I gave up. > --- > Changes from V1: > * improve change log and code comment > > arch/powerpc/include/asm/book3s/64/pgtable.h | 11 --- > 1 file changed, 8 insertions(+), 3 deletions(-) > > diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h > b/arch/powerpc/include/asm/book3s/64/pgtable.h > index 03c1a5a21c0c..cecb971674a8 100644 > --- a/arch/powerpc/include/asm/book3s/64/pgtable.h > +++ b/arch/powerpc/include/asm/book3s/64/pgtable.h > @@ -158,9 +158,14 @@ static inline void pgd_set(pgd_t *pgdp, unsigned long > val) > #define __swp_entry(type, offset)((swp_entry_t) { \ > ((type) << _PAGE_BIT_SWAP_TYPE) \ > | ((offset) << PTE_RPN_SHIFT) }) > - > -#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val((pte)) > }) > -#define __swp_entry_to_pte(x)__pte((x).val) > +/* > + * swp_entry_t should be independent of pte bits. We build a swp_entry_t from > + * swap type and offset we get from swap and convert that to pte to > + * find a matching pte in linux page table. > + * Clear bits not found in swap entries here > + */ > +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val((pte)) & > ~_PAGE_PTE }) > +#define __swp_entry_to_pte(x)__pte((x).val | _PAGE_PTE) > > #ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY > #define _PAGE_SWP_SOFT_DIRTY (1UL << (SWP_TYPE_BITS + _PAGE_BIT_SWAP_TYPE)) > -- > 2.5.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev