From: Michal Hocko <mhocko@suse.cz>
To: Johannes Weiner <hannes@cmpxchg.org>
Cc: Hugh Dickins <hughd@google.com>,
Andrew Morton <akpm@linux-foundation.org>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org
Subject: Re: [patch 2/3] mm: memcontrol: rewrite uncharge API fix - double migration
Date: Wed, 16 Jul 2014 10:34:56 +0200 [thread overview]
Message-ID: <20140716083456.GC7121@dhcp22.suse.cz> (raw)
In-Reply-To: <20140715144539.GR29639@cmpxchg.org>
[Sorry I have missed this thread]
On Tue 15-07-14 10:45:39, Johannes Weiner wrote:
[...]
> From 274b94ad83b38fe7dc1707a8eb4015b3ab1673c5 Mon Sep 17 00:00:00 2001
> From: Johannes Weiner <hannes@cmpxchg.org>
> Date: Thu, 10 Jul 2014 01:02:11 +0000
> Subject: [patch] mm: memcontrol: rewrite uncharge API fix - double migration
>
> Hugh reports:
>
> VM_BUG_ON_PAGE(!(pc->flags & PCG_MEM))
> mm/memcontrol.c:6680!
> page had count 1 mapcount 0 mapping anon index 0x196
> flags locked uptodate reclaim swapbacked, pcflags 1, memcg not root
> mem_cgroup_migrate < move_to_new_page < migrate_pages < compact_zone <
> compact_zone_order < try_to_compact_pages < __alloc_pages_direct_compact <
> __alloc_pages_nodemask < alloc_pages_vma < do_huge_pmd_anonymous_page <
> handle_mm_fault < __do_page_fault
>
> mem_cgroup_migrate() assumes that a page is only migrated once and
> then freed immediately after.
>
> However, putting the page back on the LRU list and dropping the
> isolation refcount is not done atomically. This allows a PFN-based
> migrator like compaction to isolate the page, see the expected
> anonymous page refcount of 1, and migrate the page once more.
>
> Furthermore, once the charges are transferred to the new page, the old
> page no longer has a pin on the memcg, which might get released before
> the page itself now. pc->mem_cgroup is invalid at this point, but
> PCG_USED suggests otherwise, provoking use-after-free.
The same applies to to the new page because we are transferring only
statistics. The old page with PCG_USED would uncharge the res_counter
and so the new page is not backed by any and so memcg can go away.
This sounds like a more probable scenario to me because old page should
go away quite early after successful migration.
> Properly uncharge the page after it's been migrated, including the
> clearing of PCG_USED, so that a subsequent charge migration attempt
> will be able to detect it and bail out.
>
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
> Reported-by: Hugh Dickins <hughd@google.com>
> ---
> mm/memcontrol.c | 8 +++++++-
> 1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index 1e3b27f8dc2f..1439537fe7c9 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -6655,7 +6655,6 @@ void mem_cgroup_migrate(struct page *oldpage, struct page *newpage,
>
> VM_BUG_ON_PAGE(!(pc->flags & PCG_MEM), oldpage);
> VM_BUG_ON_PAGE(do_swap_account && !(pc->flags & PCG_MEMSW), oldpage);
> - pc->flags &= ~(PCG_MEM | PCG_MEMSW);
>
> if (PageTransHuge(oldpage)) {
> nr_pages <<= compound_order(oldpage);
> @@ -6663,6 +6662,13 @@ void mem_cgroup_migrate(struct page *oldpage, struct page *newpage,
> VM_BUG_ON_PAGE(!PageTransHuge(newpage), newpage);
> }
>
> + pc->flags = 0;
> +
> + local_irq_disable();
> + mem_cgroup_charge_statistics(pc->mem_cgroup, oldpage, -nr_pages);
> + memcg_check_events(pc->mem_cgroup, oldpage);
> + local_irq_enable();
> +
> commit_charge(newpage, pc->mem_cgroup, nr_pages, lrucare);
> }
Looks good to me. I am just wondering whether we should really
fiddle with stats and events when actually nothing changed during
the transition. I would simply extract core of commit_charge into
__commit_charge which would be called from here.
The impact is minimal because events are rate limited and stats are
per-cpu so it is not a big deal it just looks ugly to me.
--
Michal Hocko
SUSE Labs
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
WARNING: multiple messages have this Message-ID (diff)
From: Michal Hocko <mhocko@suse.cz>
To: Johannes Weiner <hannes@cmpxchg.org>
Cc: Hugh Dickins <hughd@google.com>,
Andrew Morton <akpm@linux-foundation.org>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org
Subject: Re: [patch 2/3] mm: memcontrol: rewrite uncharge API fix - double migration
Date: Wed, 16 Jul 2014 10:34:56 +0200 [thread overview]
Message-ID: <20140716083456.GC7121@dhcp22.suse.cz> (raw)
In-Reply-To: <20140715144539.GR29639@cmpxchg.org>
[Sorry I have missed this thread]
On Tue 15-07-14 10:45:39, Johannes Weiner wrote:
[...]
> From 274b94ad83b38fe7dc1707a8eb4015b3ab1673c5 Mon Sep 17 00:00:00 2001
> From: Johannes Weiner <hannes@cmpxchg.org>
> Date: Thu, 10 Jul 2014 01:02:11 +0000
> Subject: [patch] mm: memcontrol: rewrite uncharge API fix - double migration
>
> Hugh reports:
>
> VM_BUG_ON_PAGE(!(pc->flags & PCG_MEM))
> mm/memcontrol.c:6680!
> page had count 1 mapcount 0 mapping anon index 0x196
> flags locked uptodate reclaim swapbacked, pcflags 1, memcg not root
> mem_cgroup_migrate < move_to_new_page < migrate_pages < compact_zone <
> compact_zone_order < try_to_compact_pages < __alloc_pages_direct_compact <
> __alloc_pages_nodemask < alloc_pages_vma < do_huge_pmd_anonymous_page <
> handle_mm_fault < __do_page_fault
>
> mem_cgroup_migrate() assumes that a page is only migrated once and
> then freed immediately after.
>
> However, putting the page back on the LRU list and dropping the
> isolation refcount is not done atomically. This allows a PFN-based
> migrator like compaction to isolate the page, see the expected
> anonymous page refcount of 1, and migrate the page once more.
>
> Furthermore, once the charges are transferred to the new page, the old
> page no longer has a pin on the memcg, which might get released before
> the page itself now. pc->mem_cgroup is invalid at this point, but
> PCG_USED suggests otherwise, provoking use-after-free.
The same applies to to the new page because we are transferring only
statistics. The old page with PCG_USED would uncharge the res_counter
and so the new page is not backed by any and so memcg can go away.
This sounds like a more probable scenario to me because old page should
go away quite early after successful migration.
> Properly uncharge the page after it's been migrated, including the
> clearing of PCG_USED, so that a subsequent charge migration attempt
> will be able to detect it and bail out.
>
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
> Reported-by: Hugh Dickins <hughd@google.com>
> ---
> mm/memcontrol.c | 8 +++++++-
> 1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index 1e3b27f8dc2f..1439537fe7c9 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -6655,7 +6655,6 @@ void mem_cgroup_migrate(struct page *oldpage, struct page *newpage,
>
> VM_BUG_ON_PAGE(!(pc->flags & PCG_MEM), oldpage);
> VM_BUG_ON_PAGE(do_swap_account && !(pc->flags & PCG_MEMSW), oldpage);
> - pc->flags &= ~(PCG_MEM | PCG_MEMSW);
>
> if (PageTransHuge(oldpage)) {
> nr_pages <<= compound_order(oldpage);
> @@ -6663,6 +6662,13 @@ void mem_cgroup_migrate(struct page *oldpage, struct page *newpage,
> VM_BUG_ON_PAGE(!PageTransHuge(newpage), newpage);
> }
>
> + pc->flags = 0;
> +
> + local_irq_disable();
> + mem_cgroup_charge_statistics(pc->mem_cgroup, oldpage, -nr_pages);
> + memcg_check_events(pc->mem_cgroup, oldpage);
> + local_irq_enable();
> +
> commit_charge(newpage, pc->mem_cgroup, nr_pages, lrucare);
> }
Looks good to me. I am just wondering whether we should really
fiddle with stats and events when actually nothing changed during
the transition. I would simply extract core of commit_charge into
__commit_charge which would be called from here.
The impact is minimal because events are rate limited and stats are
per-cpu so it is not a big deal it just looks ugly to me.
--
Michal Hocko
SUSE Labs
next prev parent reply other threads:[~2014-07-16 8:35 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-07-07 18:52 [patch 0/3] mm: memcontrol: rewrite uncharge API follow-up fixes Johannes Weiner
2014-07-07 18:52 ` Johannes Weiner
2014-07-07 18:52 ` [patch 1/3] mm: memcontrol: rewrite uncharge API fix - uncharge from IRQ context Johannes Weiner
2014-07-07 18:52 ` Johannes Weiner
2014-07-07 18:52 ` [patch 2/3] mm: memcontrol: rewrite uncharge API fix - double migration Johannes Weiner
2014-07-07 18:52 ` Johannes Weiner
2014-07-14 19:57 ` Hugh Dickins
2014-07-14 19:57 ` Hugh Dickins
2014-07-15 14:45 ` Johannes Weiner
2014-07-15 14:45 ` Johannes Weiner
2014-07-15 22:14 ` Hugh Dickins
2014-07-15 22:14 ` Hugh Dickins
2014-07-16 8:34 ` Michal Hocko [this message]
2014-07-16 8:34 ` Michal Hocko
2014-07-16 16:04 ` Johannes Weiner
2014-07-16 16:04 ` Johannes Weiner
2014-07-16 19:28 ` Michal Hocko
2014-07-16 19:28 ` Michal Hocko
2014-07-07 18:52 ` [patch 3/3] mm: memcontrol: rewrite uncharge API fix - migrate before re-mapping Johannes Weiner
2014-07-07 18:52 ` Johannes Weiner
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=20140716083456.GC7121@dhcp22.suse.cz \
--to=mhocko@suse.cz \
--cc=akpm@linux-foundation.org \
--cc=hannes@cmpxchg.org \
--cc=hughd@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.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.