All of lore.kernel.org
 help / color / mirror / Atom feed
From: Greg KH <greg@kroah.com>
To: Vlastimil Babka <vbabka@suse.cz>
Cc: stable@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-mm@kvack.org, x86@kernel.org, Jann Horn <jannh@google.com>,
	Ben Hutchings <ben.hutchings@codethink.co.uk>,
	xen-devel@lists.xenproject.org,
	Oscar Salvador <osalvador@suse.de>,
	Thomas Gleixner <tglx@linutronix.de>,
	Ingo Molnar <mingo@redhat.com>,
	Peter Zijlstra <peterz@infradead.org>,
	Juergen Gross <jgross@suse.com>,
	"Kirill A . Shutemov" <kirill.shutemov@linux.intel.com>,
	Vitaly Kuznetsov <vkuznets@redhat.com>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Borislav Petkov <bp@alien8.de>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	Andy Lutomirski <luto@kernel.org>
Subject: Re: [PATCH STABLE 4.9] x86, mm, gup: prevent get_page() race with munmap in paravirt guest
Date: Mon, 5 Aug 2019 13:58:24 +0200	[thread overview]
Message-ID: <20190805115824.GC8189@kroah.com> (raw)
In-Reply-To: <20190802160614.8089-1-vbabka@suse.cz>

On Fri, Aug 02, 2019 at 06:06:14PM +0200, Vlastimil Babka wrote:
> The x86 version of get_user_pages_fast() relies on disabled interrupts to
> synchronize gup_pte_range() between gup_get_pte(ptep); and get_page() against
> a parallel munmap. The munmap side nulls the pte, then flushes TLBs, then
> releases the page. As TLB flush is done synchronously via IPI disabling
> interrupts blocks the page release, and get_page(), which assumes existing
> reference on page, is thus safe.
> However when TLB flush is done by a hypercall, e.g. in a Xen PV guest, there is
> no blocking thanks to disabled interrupts, and get_page() can succeed on a page
> that was already freed or even reused.
> 
> We have recently seen this happen with our 4.4 and 4.12 based kernels, with
> userspace (java) that exits a thread, where mm_release() performs a futex_wake()
> on tsk->clear_child_tid, and another thread in parallel unmaps the page where
> tsk->clear_child_tid points to. The spurious get_page() succeeds, but futex code
> immediately releases the page again, while it's already on a freelist. Symptoms
> include a bad page state warning, general protection faults acessing a poisoned
> list prev/next pointer in the freelist, or free page pcplists of two cpus joined
> together in a single list. Oscar has also reproduced this scenario, with a
> patch inserting delays before the get_page() to make the race window larger.
> 
> Fix this by removing the dependency on TLB flush interrupts the same way as the
> generic get_user_pages_fast() code by using page_cache_add_speculative() and
> revalidating the PTE contents after pinning the page. Mainline is safe since
> 4.13 where the x86 gup code was removed in favor of the common code. Accessing
> the page table itself safely also relies on disabled interrupts and TLB flush
> IPIs that don't happen with hypercalls, which was acknowledged in commit
> 9e52fc2b50de ("x86/mm: Enable RCU based page table freeing
> (CONFIG_HAVE_RCU_TABLE_FREE=y)"). That commit with follups should also be
> backported for full safety, although our reproducer didn't hit a problem
> without that backport.
> 
> Reproduced-by: Oscar Salvador <osalvador@suse.de>
> Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Juergen Gross <jgross@suse.com>
> Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
> Cc: Vitaly Kuznetsov <vkuznets@redhat.com>
> Cc: Linus Torvalds <torvalds@linux-foundation.org>
> Cc: Borislav Petkov <bp@alien8.de>
> Cc: Dave Hansen <dave.hansen@linux.intel.com>
> Cc: Andy Lutomirski <luto@kernel.org>
> ---
> 
> Hi, I'm sending this stable-only patch for consideration because it's probably
> unrealistic to backport the 4.13 switch to generic GUP. I can look at 4.4 and
> 3.16 if accepted. The RCU page table freeing could be also considered.
> Note the patch also includes page refcount protection. I found out that
> 8fde12ca79af ("mm: prevent get_user_pages() from overflowing page refcount")
> backport to 4.9 missed the arch-specific gup implementations:
> https://lore.kernel.org/lkml/6650323f-dbc9-f069-000b-f6b0f941a065@suse.cz/

This looks sane to me, thank you for the backport.  I've queued it up
now, and if anyone has any objections, please let me know.

thanks,

greg k-h

WARNING: multiple messages have this Message-ID (diff)
From: Greg KH <greg@kroah.com>
To: Vlastimil Babka <vbabka@suse.cz>
Cc: Juergen Gross <jgross@suse.com>,
	Ben Hutchings <ben.hutchings@codethink.co.uk>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	Jann Horn <jannh@google.com>,
	Peter Zijlstra <peterz@infradead.org>,
	x86@kernel.org, linux-kernel@vger.kernel.org,
	stable@vger.kernel.org, linux-mm@kvack.org,
	Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
	Andy Lutomirski <luto@kernel.org>,
	xen-devel@lists.xenproject.org,
	Thomas Gleixner <tglx@linutronix.de>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Vitaly Kuznetsov <vkuznets@redhat.com>,
	"Kirill A . Shutemov" <kirill.shutemov@linux.intel.com>,
	Oscar Salvador <osalvador@suse.de>
Subject: Re: [Xen-devel] [PATCH STABLE 4.9] x86, mm, gup: prevent get_page() race with munmap in paravirt guest
Date: Mon, 5 Aug 2019 13:58:24 +0200	[thread overview]
Message-ID: <20190805115824.GC8189@kroah.com> (raw)
In-Reply-To: <20190802160614.8089-1-vbabka@suse.cz>

On Fri, Aug 02, 2019 at 06:06:14PM +0200, Vlastimil Babka wrote:
> The x86 version of get_user_pages_fast() relies on disabled interrupts to
> synchronize gup_pte_range() between gup_get_pte(ptep); and get_page() against
> a parallel munmap. The munmap side nulls the pte, then flushes TLBs, then
> releases the page. As TLB flush is done synchronously via IPI disabling
> interrupts blocks the page release, and get_page(), which assumes existing
> reference on page, is thus safe.
> However when TLB flush is done by a hypercall, e.g. in a Xen PV guest, there is
> no blocking thanks to disabled interrupts, and get_page() can succeed on a page
> that was already freed or even reused.
> 
> We have recently seen this happen with our 4.4 and 4.12 based kernels, with
> userspace (java) that exits a thread, where mm_release() performs a futex_wake()
> on tsk->clear_child_tid, and another thread in parallel unmaps the page where
> tsk->clear_child_tid points to. The spurious get_page() succeeds, but futex code
> immediately releases the page again, while it's already on a freelist. Symptoms
> include a bad page state warning, general protection faults acessing a poisoned
> list prev/next pointer in the freelist, or free page pcplists of two cpus joined
> together in a single list. Oscar has also reproduced this scenario, with a
> patch inserting delays before the get_page() to make the race window larger.
> 
> Fix this by removing the dependency on TLB flush interrupts the same way as the
> generic get_user_pages_fast() code by using page_cache_add_speculative() and
> revalidating the PTE contents after pinning the page. Mainline is safe since
> 4.13 where the x86 gup code was removed in favor of the common code. Accessing
> the page table itself safely also relies on disabled interrupts and TLB flush
> IPIs that don't happen with hypercalls, which was acknowledged in commit
> 9e52fc2b50de ("x86/mm: Enable RCU based page table freeing
> (CONFIG_HAVE_RCU_TABLE_FREE=y)"). That commit with follups should also be
> backported for full safety, although our reproducer didn't hit a problem
> without that backport.
> 
> Reproduced-by: Oscar Salvador <osalvador@suse.de>
> Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Juergen Gross <jgross@suse.com>
> Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
> Cc: Vitaly Kuznetsov <vkuznets@redhat.com>
> Cc: Linus Torvalds <torvalds@linux-foundation.org>
> Cc: Borislav Petkov <bp@alien8.de>
> Cc: Dave Hansen <dave.hansen@linux.intel.com>
> Cc: Andy Lutomirski <luto@kernel.org>
> ---
> 
> Hi, I'm sending this stable-only patch for consideration because it's probably
> unrealistic to backport the 4.13 switch to generic GUP. I can look at 4.4 and
> 3.16 if accepted. The RCU page table freeing could be also considered.
> Note the patch also includes page refcount protection. I found out that
> 8fde12ca79af ("mm: prevent get_user_pages() from overflowing page refcount")
> backport to 4.9 missed the arch-specific gup implementations:
> https://lore.kernel.org/lkml/6650323f-dbc9-f069-000b-f6b0f941a065@suse.cz/

This looks sane to me, thank you for the backport.  I've queued it up
now, and if anyone has any objections, please let me know.

thanks,

greg k-h

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

  reply	other threads:[~2019-08-05 11:58 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-08-02 16:06 [PATCH STABLE 4.9] x86, mm, gup: prevent get_page() race with munmap in paravirt guest Vlastimil Babka
2019-08-02 16:06 ` [Xen-devel] " Vlastimil Babka
2019-08-05 11:58 ` Greg KH [this message]
2019-08-05 11:58   ` Greg KH
2019-08-05 12:25 ` Patch "x86, mm, gup: prevent get_page() race with munmap in paravirt guest" has been added to the 4.9-stable tree gregkh
2019-08-05 12:25   ` [Xen-devel] " gregkh
2019-09-19 18:26 ` [PATCH STABLE 4.9] x86, mm, gup: prevent get_page() race with munmap in paravirt guest Ben Hutchings
2019-09-19 18:26   ` [Xen-devel] " Ben Hutchings
2019-09-19 18:26   ` Ben Hutchings
2019-09-23  8:48   ` Vlastimil Babka
2019-09-23  8:48     ` [Xen-devel] " Vlastimil Babka
2019-11-06 17:18   ` Vlastimil Babka
2019-11-06 17:18     ` [Xen-devel] " Vlastimil Babka

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190805115824.GC8189@kroah.com \
    --to=greg@kroah.com \
    --cc=ben.hutchings@codethink.co.uk \
    --cc=bp@alien8.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=jannh@google.com \
    --cc=jgross@suse.com \
    --cc=kirill.shutemov@linux.intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=luto@kernel.org \
    --cc=mingo@redhat.com \
    --cc=osalvador@suse.de \
    --cc=peterz@infradead.org \
    --cc=stable@vger.kernel.org \
    --cc=tglx@linutronix.de \
    --cc=torvalds@linux-foundation.org \
    --cc=vbabka@suse.cz \
    --cc=vkuznets@redhat.com \
    --cc=x86@kernel.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.