Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1375753

Re: [PATCH 09/31] huge tmpfs: avoid premature exposure of new pagetable

From "Kirill A. Shutemov" <kirill@shutemov.name>
Newsgroups linux.kernel
Subject Re: [PATCH 09/31] huge tmpfs: avoid premature exposure of new pagetable
Date 2016-04-11 14:00 +0200
Message-ID <rmIFA-5ju-11@gated-at.bofh.it> (permalink)
References <rkGye-1F1-7@gated-at.bofh.it> <rkGHU-1Ji-33@gated-at.bofh.it>
Organization linux.* mail to news gateway

Show all headers | View raw


On Tue, Apr 05, 2016 at 02:24:23PM -0700, Hugh Dickins wrote:
> In early development, a huge tmpfs fault simply replaced the pmd which
> pointed to the empty pagetable just allocated in __handle_mm_fault():
> but that is unsafe.
> 
> Andrea wrote a very interesting comment on THP in mm/memory.c,
> just before the end of __handle_mm_fault():
> 
>  * A regular pmd is established and it can't morph into a huge pmd
>  * from under us anymore at this point because we hold the mmap_sem
>  * read mode and khugepaged takes it in write mode. So now it's
>  * safe to run pte_offset_map().
> 
> This comment hints at several difficulties, which anon THP solved
> for itself with mmap_sem and anon_vma lock, but which huge tmpfs
> may need to solve differently.
> 
> The reference to pte_offset_map() above: I believe that's a hint
> that on a 32-bit machine, the pagetables might need to come from
> kernel-mapped memory, but a huge pmd pointing to user memory beyond
> that limit could be racily substituted, causing undefined behavior
> in the architecture-dependent pte_offset_map().
> 
> That itself is not a problem on x86_64, but there's plenty more:
> how about those places which use pte_offset_map_lock() - if that
> spinlock is in the struct page of a pagetable, which has been
> deposited and might be withdrawn and freed at any moment (being
> on a list unattached to the allocating pmd in the case of x86),
> taking the spinlock might corrupt someone else's struct page.
> 
> Because THP has departed from the earlier rules (when pagetable
> was only freed under exclusive mmap_sem, or at exit_mmap, after
> removing all affected vmas from the rmap list): zap_huge_pmd()
> does pte_free() even when serving MADV_DONTNEED under down_read
> of mmap_sem.

Emm.. The pte table freed from zap_huge_pmd() is from deposit. It wasn't
linked into process' page table tree. So I don't see how THP has departed
from the rules.

I don't think it changes anything to implementation, but this part of
commit message, I believe, is inaccurate.

> And what of the "entry = *pte" at the start of handle_pte_fault(),
> getting the entry used in pte_same(,orig_pte) tests to validate all
> fault handling?  If that entry can itself be junk picked out of some
> freed and reused pagetable, it's hard to estimate the consequences.
> 
> We need to consider the safety of concurrent faults, and the
> safety of rmap lookups, and the safety of miscellaneous operations
> such as smaps_pte_range() for reading /proc/<pid>/smaps.
> 
> I set out to make safe the places which descend pgd,pud,pmd,pte,
> using more careful access techniques like mm_find_pmd(); but with
> pte_offset_map() being architecture-defined, found it too big a job
> to tighten up all over.
> 
> Instead, approach from the opposite direction: just do not expose
> a pagetable in an empty *pmd, until vm_ops->fault has had a chance
> to ask for a huge pmd there.  This is a much easier change to make,
> and we are lucky that all the driver faults appear to be using
> interfaces (like vm_insert_page() and remap_pfn_range()) which
> automatically do the pte_alloc() if it was not already done.
> 
> But we must not get stuck refaulting: need FAULT_FLAG_MAY_HUGE for
> __do_fault() to tell shmem_fault() to try for huge only when *pmd is
> empty (could instead add pmd to vmf and let shmem work that out for
> itself, but probably better to hide pmd from vm_ops->faults).
> 
> Without a pagetable to hold the pte_none() entry found in a newly
> allocated pagetable, handle_pte_fault() would like to provide a static
> none entry for later orig_pte checks.  But architectures have never had
> to provide that definition before; and although almost all use zeroes
> for an empty pagetable, a few do not - nios2, s390, um, xtensa.
> 
> Never mind, forget about pte_same(,orig_pte), the three __do_fault()
> callers can follow do_anonymous_page(), and just use a pte_none() check.
> 
> do_fault_around() presents one last problem: it wants pagetable to
> have been allocated, but was being called by do_read_fault() before
> __do_fault().  I see no disadvantage to moving it after, allowing huge
> pmd to be chosen first; but Kirill reports additional radix-tree lookup
> in hot pagecache case when he implemented faultaround: needs further
> investigation.

In my implementation faultaround can establish PMD mappings. So there's no
disadvantage to call faultaround first.

And if faultaround happened to solve the page fault we don't need to do
usual ->fault lookup.

> Note: after months of use, we recently hit an OOM deadlock: this patch
> moves the new pagetable allocation inside where page lock is held on a
> pagecache page, and exit's munlock_vma_pages_all() takes page lock on
> all mlocked pages.  Both parties are behaving badly: we hope to change
> munlock to use trylock_page() instead, but should certainly switch here
> to preallocating the pagetable outside the page lock.  But I've not yet
> written and tested that change.

Hm. Okay, I need to fix this in my implementation too. It shouldn't be too
hard as I have fe->pte_prealloc around already.

-- 
 Kirill A. Shutemov

Back to linux.kernel | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

[PATCH 00/31] huge tmpfs: THPagecache implemented by teams Hugh Dickins <hughd@google.com> - 2016-04-05 23:20 +0200
  [PATCH 03/31] huge tmpfs: huge=N mount option and  /proc/sys/vm/shmem_huge Hugh Dickins <hughd@google.com> - 2016-04-05 23:20 +0200
    Re: [PATCH 03/31] huge tmpfs: huge=N mount option and  /proc/sys/vm/shmem_huge "Kirill A. Shutemov" <kirill@shutemov.name> - 2016-04-11 13:20 +0200
  [PATCH 02/31] huge tmpfs: include shmem freeholes in available  memory Hugh Dickins <hughd@google.com> - 2016-04-05 23:20 +0200
  [PATCH 08/31] huge tmpfs: try_to_unmap_one use  page_check_address_transhuge Hugh Dickins <hughd@google.com> - 2016-04-05 23:30 +0200
  [PATCH 11/31] huge tmpfs: disband split huge pmds on race or memory  failure Hugh Dickins <hughd@google.com> - 2016-04-05 23:30 +0200
  [PATCH 06/31] huge tmpfs: shrinker to migrate and free underused  holes Hugh Dickins <hughd@google.com> - 2016-04-05 23:30 +0200
  [PATCH 10/31] huge tmpfs: map shmem by huge page pmd or by page team  ptes Hugh Dickins <hughd@google.com> - 2016-04-05 23:30 +0200
  [PATCH 07/31] huge tmpfs: get_unmapped_area align & fault supply  huge page Hugh Dickins <hughd@google.com> - 2016-04-05 23:30 +0200
  [PATCH 09/31] huge tmpfs: avoid premature exposure of new  pagetable Hugh Dickins <hughd@google.com> - 2016-04-05 23:30 +0200
    Re: [PATCH 09/31] huge tmpfs: avoid premature exposure of new  pagetable "Kirill A. Shutemov" <kirill@shutemov.name> - 2016-04-11 14:00 +0200
  [PATCH 13/31] huge tmpfs: use Unevictable lru with variable  hpage_nr_pages Hugh Dickins <hughd@google.com> - 2016-04-05 23:40 +0200
  [PATCH 12/31] huge tmpfs: extend get_user_pages_fast to shmem pmd Hugh Dickins <hughd@google.com> - 2016-04-05 23:40 +0200
    Re: [PATCH 12/31] huge tmpfs: extend get_user_pages_fast to shmem pmd Ingo Molnar <mingo@kernel.org> - 2016-04-06 09:10 +0200
      Re: [PATCH 12/31] huge tmpfs: extend get_user_pages_fast to shmem  pmd Hugh Dickins <hughd@google.com> - 2016-04-07 05:00 +0200
        Re: [PATCH 12/31] huge tmpfs: extend get_user_pages_fast to shmem pmd Ingo Molnar <mingo@kernel.org> - 2016-04-13 11:00 +0200
  [PATCH 16/31] kvm: plumb return of hva when resolving page fault. Hugh Dickins <hughd@google.com> - 2016-04-05 23:40 +0200
  [PATCH 14/31] huge tmpfs: fix Mlocked meminfo, track huge & unhuge  mlocks Hugh Dickins <hughd@google.com> - 2016-04-05 23:40 +0200
  [PATCH 15/31] huge tmpfs: fix Mapped meminfo, track huge & unhuge  mappings Hugh Dickins <hughd@google.com> - 2016-04-05 23:40 +0200
  [PATCH 18/31] huge tmpfs: mem_cgroup move charge on shmem huge  pages Hugh Dickins <hughd@google.com> - 2016-04-05 23:50 +0200
  [PATCH 17/31] kvm: teach kvm to map page teams as huge pages. Hugh Dickins <hughd@google.com> - 2016-04-05 23:50 +0200
    Re: [PATCH 17/31] kvm: teach kvm to map page teams as huge pages. Paolo Bonzini <pbonzini@redhat.com> - 2016-04-06 01:40 +0200
      Re: [PATCH 17/31] kvm: teach kvm to map page teams as huge pages. Hugh Dickins <hughd@google.com> - 2016-04-06 03:20 +0200
        Re: [PATCH 17/31] kvm: teach kvm to map page teams as huge pages. Paolo Bonzini <pbonzini@redhat.com> - 2016-04-06 08:50 +0200
  [PATCH 19/31] huge tmpfs: mem_cgroup shmem_pmdmapped accounting Hugh Dickins <hughd@google.com> - 2016-04-05 23:50 +0200
  [PATCH 20/31] huge tmpfs: mem_cgroup shmem_hugepages accounting Hugh Dickins <hughd@google.com> - 2016-04-05 23:50 +0200
  [PATCH 22/31] huge tmpfs: /proc/<pid>/smaps show ShmemHugePages Hugh Dickins <hughd@google.com> - 2016-04-06 00:00 +0200
  [PATCH 24/31] huge tmpfs recovery: shmem_recovery_populate to fill  huge page Hugh Dickins <hughd@google.com> - 2016-04-06 00:00 +0200
  [PATCH 21/31] huge tmpfs: show page team flag in pageflags Hugh Dickins <hughd@google.com> - 2016-04-06 00:00 +0200
  [PATCH 25/31] huge tmpfs recovery: shmem_recovery_remap &  remap_team_by_pmd Hugh Dickins <hughd@google.com> - 2016-04-06 00:00 +0200
  [PATCH 26/31] huge tmpfs recovery: shmem_recovery_swapin to read  from swap Hugh Dickins <hughd@google.com> - 2016-04-06 00:00 +0200
  [PATCH 23/31] huge tmpfs recovery: framework for reconstituting huge  pages Hugh Dickins <hughd@google.com> - 2016-04-06 00:00 +0200
    Re: [PATCH 23/31] huge tmpfs recovery: framework for reconstituting  huge pages Mika Penttilä <mika.penttila@nextfour.com> - 2016-04-06 12:30 +0200
      Re: [PATCH 23/31] huge tmpfs recovery: framework for reconstituting  huge pages Hugh Dickins <hughd@google.com> - 2016-04-07 04:10 +0200
  [PATCH 31/31] huge tmpfs: no kswapd by default on sync allocations Hugh Dickins <hughd@google.com> - 2016-04-06 00:10 +0200
  [PATCH 27/31] huge tmpfs recovery: tweak shmem_getpage_gfp to fill  team Hugh Dickins <hughd@google.com> - 2016-04-06 00:10 +0200
  [PATCH 28/31] huge tmpfs recovery: debugfs stats to complete this  phase Hugh Dickins <hughd@google.com> - 2016-04-06 00:10 +0200
  [PATCH 30/31] huge tmpfs: shmem_huge_gfpmask and  shmem_recovery_gfpmask Hugh Dickins <hughd@google.com> - 2016-04-06 00:10 +0200
  [PATCH 29/31] huge tmpfs recovery: page migration call back into  shmem Hugh Dickins <hughd@google.com> - 2016-04-06 00:10 +0200

csiph-web