All of lore.kernel.org
 help / color / mirror / Atom feed
From: Matthew Wilcox <willy-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org>
To: Hugh Dickins <hughd-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
Cc: Johannes Weiner <hannes-druUgvl0LCNAfugRpC6u6w@public.gmane.org>,
	Andrew Morton
	<akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>,
	Michal Hocko <mhocko-IBi9RG/b67k@public.gmane.org>,
	Zhou Guanghui
	<zhouguanghui1-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>,
	Zi Yan <ziy-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>,
	Shakeel Butt <shakeelb-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>,
	Roman Gushchin <guro-b10kYP2dOMg@public.gmane.org>,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org,
	cgroups-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	kernel-team-b10kYP2dOMg@public.gmane.org
Subject: Re: [PATCH] mm: page_alloc: fix memcg accounting leak in speculative cache lookup
Date: Sat, 20 Mar 2021 03:25:56 +0000	[thread overview]
Message-ID: <20210320032556.GD3420@casper.infradead.org> (raw)
In-Reply-To: <alpine.LSU.2.11.2103191814040.1043-fupSdm12i1nKWymIFiNcPA@public.gmane.org>

On Fri, Mar 19, 2021 at 06:52:58PM -0700, Hugh Dickins wrote:
> > +	/*
> > +	 * Drop the base reference from __alloc_pages and free. In
> > +	 * case there is an outstanding speculative reference, from
> > +	 * e.g. the page cache, it will put and free the page later.
> > +	 */
> > +	if (likely(put_page_testzero(page))) {
> >  		free_the_page(page, order);
> > -	else if (!PageHead(page))
> > +		return;
> > +	}
> > +
> > +	/*
> > +	 * The speculative reference will put and free the page.
> > +	 *
> > +	 * However, if the speculation was into a higher-order page
> > +	 * chunk that isn't marked compound, the other side will know
> > +	 * nothing about our buddy pages and only free the order-0
> > +	 * page at the start of our chunk! We must split off and free
> > +	 * the buddy pages here.
> > +	 *
> > +	 * The buddy pages aren't individually refcounted, so they
> > +	 * can't have any pending speculative references themselves.
> > +	 */
> > +	if (!PageHead(page) && order > 0) {
> 
> The put_page_testzero() has released our reference to the first
> subpage of page: it's now under the control of the racing speculative
> lookup.  So it seems to me unsafe to be checking PageHead(page) here:
> if it was actually a compound page, PageHead might already be cleared
> by now, and we doubly free its tail pages below?  I think we need to
> use a "bool compound = PageHead(page)" on entry to __free_pages().
> 
> Or alternatively, it's wrong to call __free_pages() on a compound
> page anyway, so we should not check PageHead at all, except in a
> WARN_ON_ONCE(PageCompound(page)) at the start?

Alas ...

$ git grep '__free_pages\>.*compound'
drivers/dma-buf/heaps/system_heap.c:            __free_pages(page, compound_order(page));
drivers/dma-buf/heaps/system_heap.c:            __free_pages(p, compound_order(p));
drivers/dma-buf/heaps/system_heap.c:            __free_pages(page, compound_order(page));
mm/huge_memory.c:               __free_pages(zero_page, compound_order(zero_page));
mm/huge_memory.c:               __free_pages(zero_page, compound_order(zero_page));
mm/slub.c:                      __free_pages(page, compound_order(page));

Maybe we should disallow it!

There are a few other places to check:

$ grep -l __GFP_COMP $(git grep -lw __free_pages) | wc -l
24

(assuming the pages are allocated and freed in the same file, which is a
reasonable approximation, but not guaranteed to catch everything.  Many
of these 24 will be false positives, of course.)

WARNING: multiple messages have this Message-ID (diff)
From: Matthew Wilcox <willy@infradead.org>
To: Hugh Dickins <hughd@google.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	Michal Hocko <mhocko@suse.com>,
	Zhou Guanghui <zhouguanghui1@huawei.com>, Zi Yan <ziy@nvidia.com>,
	Shakeel Butt <shakeelb@google.com>, Roman Gushchin <guro@fb.com>,
	linux-mm@kvack.org, cgroups@vger.kernel.org,
	linux-kernel@vger.kernel.org, kernel-team@fb.com
Subject: Re: [PATCH] mm: page_alloc: fix memcg accounting leak in speculative cache lookup
Date: Sat, 20 Mar 2021 03:25:56 +0000	[thread overview]
Message-ID: <20210320032556.GD3420@casper.infradead.org> (raw)
In-Reply-To: <alpine.LSU.2.11.2103191814040.1043@eggly.anvils>

On Fri, Mar 19, 2021 at 06:52:58PM -0700, Hugh Dickins wrote:
> > +	/*
> > +	 * Drop the base reference from __alloc_pages and free. In
> > +	 * case there is an outstanding speculative reference, from
> > +	 * e.g. the page cache, it will put and free the page later.
> > +	 */
> > +	if (likely(put_page_testzero(page))) {
> >  		free_the_page(page, order);
> > -	else if (!PageHead(page))
> > +		return;
> > +	}
> > +
> > +	/*
> > +	 * The speculative reference will put and free the page.
> > +	 *
> > +	 * However, if the speculation was into a higher-order page
> > +	 * chunk that isn't marked compound, the other side will know
> > +	 * nothing about our buddy pages and only free the order-0
> > +	 * page at the start of our chunk! We must split off and free
> > +	 * the buddy pages here.
> > +	 *
> > +	 * The buddy pages aren't individually refcounted, so they
> > +	 * can't have any pending speculative references themselves.
> > +	 */
> > +	if (!PageHead(page) && order > 0) {
> 
> The put_page_testzero() has released our reference to the first
> subpage of page: it's now under the control of the racing speculative
> lookup.  So it seems to me unsafe to be checking PageHead(page) here:
> if it was actually a compound page, PageHead might already be cleared
> by now, and we doubly free its tail pages below?  I think we need to
> use a "bool compound = PageHead(page)" on entry to __free_pages().
> 
> Or alternatively, it's wrong to call __free_pages() on a compound
> page anyway, so we should not check PageHead at all, except in a
> WARN_ON_ONCE(PageCompound(page)) at the start?

Alas ...

$ git grep '__free_pages\>.*compound'
drivers/dma-buf/heaps/system_heap.c:            __free_pages(page, compound_order(page));
drivers/dma-buf/heaps/system_heap.c:            __free_pages(p, compound_order(p));
drivers/dma-buf/heaps/system_heap.c:            __free_pages(page, compound_order(page));
mm/huge_memory.c:               __free_pages(zero_page, compound_order(zero_page));
mm/huge_memory.c:               __free_pages(zero_page, compound_order(zero_page));
mm/slub.c:                      __free_pages(page, compound_order(page));

Maybe we should disallow it!

There are a few other places to check:

$ grep -l __GFP_COMP $(git grep -lw __free_pages) | wc -l
24

(assuming the pages are allocated and freed in the same file, which is a
reasonable approximation, but not guaranteed to catch everything.  Many
of these 24 will be false positives, of course.)


  parent reply	other threads:[~2021-03-20  3:25 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-19  7:15 [PATCH] mm: page_alloc: fix memcg accounting leak in speculative cache lookup Johannes Weiner
2021-03-19 13:21 ` Matthew Wilcox
     [not found] ` <20210319071547.60973-1-hannes-druUgvl0LCNAfugRpC6u6w@public.gmane.org>
2021-03-20  1:52   ` Hugh Dickins
2021-03-20  1:52     ` Hugh Dickins
     [not found]     ` <alpine.LSU.2.11.2103191814040.1043-fupSdm12i1nKWymIFiNcPA@public.gmane.org>
2021-03-20  3:25       ` Matthew Wilcox [this message]
2021-03-20  3:25         ` Matthew Wilcox
2021-03-23 19:02     ` Johannes Weiner
2021-03-23 19:12       ` Matthew Wilcox
2021-03-23 20:10       ` Hugh Dickins
     [not found]         ` <alpine.LSU.2.11.2103231310020.5513-fupSdm12i1nKWymIFiNcPA@public.gmane.org>
2021-03-26  1:55           ` Hugh Dickins
2021-03-26  1:55             ` Hugh Dickins
     [not found]             ` <alpine.LSU.2.11.2103251716160.12404-fupSdm12i1nKWymIFiNcPA@public.gmane.org>
2021-03-26  2:51               ` Matthew Wilcox
2021-03-26  2:51                 ` Matthew Wilcox
     [not found]                 ` <20210326025143.GB1719932-FZi0V3Vbi30CUdFEqe4BF2D2FQJk+8+b@public.gmane.org>
2021-03-26  4:04                   ` Hugh Dickins
2021-03-26  4:04                     ` Hugh Dickins
     [not found]                     ` <alpine.LSU.2.11.2103252018170.13067-fupSdm12i1nKWymIFiNcPA@public.gmane.org>
2021-03-26 12:07                       ` Matthew Wilcox
2021-03-26 12:07                         ` Matthew Wilcox
2021-03-24  8:58       ` Michal Hocko
2021-03-22  9:55 ` Michal Hocko

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=20210320032556.GD3420@casper.infradead.org \
    --to=willy-wegcikhe2lqwvfeawa7xhq@public.gmane.org \
    --cc=akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org \
    --cc=cgroups-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=guro-b10kYP2dOMg@public.gmane.org \
    --cc=hannes-druUgvl0LCNAfugRpC6u6w@public.gmane.org \
    --cc=hughd-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org \
    --cc=kernel-team-b10kYP2dOMg@public.gmane.org \
    --cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-mm-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org \
    --cc=mhocko-IBi9RG/b67k@public.gmane.org \
    --cc=shakeelb-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org \
    --cc=zhouguanghui1-hv44wF8Li93QT0dZR+AlfA@public.gmane.org \
    --cc=ziy-DDmLM1+adcrQT0dZR+AlfA@public.gmane.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.