Re: [RFC PATCH] net: Fix one page_pool page leak from skb_frag_unref

Jakub Kicinski
2024-05-03T00:46:19Z

On Thu, 2 May 2024 13:08:23 -0700 Mina Almasry wrote:
> OK, this is where I'm not sure anymore. The diff you're replying to
> attempts to enforce the invariant: "if anyone wants a reference on an
> skb_frag, skb_frag_ref will be a pp ref on pp frags
> (is_pp_page==true), and page refs on non-pp frags
> (is_pp_page==false)".
>
> Additionally the page doesn't transition from pp to non-pp and vice
> versa while anyone is holding a pp ref, because
> page_pool_set_pp_info() is called right after the page is obtained
> from the buddy allocator (before released from the page pool) and
> page_pool_clear_pp_info() is called only after all the pp refs are
> dropped.
>
> So:
>
> 1. We know the caller has a ref (otherwise get_page() wouldn't be safe
> in the non-pp case).
> 2. We know that the page has not transitioned from pp to non-pp or
> vice versa since the caller obtained the ref (from code inspection, pp

How do we know that?

> info is not changed until all the refs are dropped for pp pages).
> 3. AFAICT, it follows that if the page is pp, then the caller has a pp
> ref, and if the page is non-pp, then the caller has a page ref.

If that's true we have nothing to worry about.

> 4. So, if is_pp_page==true, then the caller has a pp ref, then
> napi_pp_get_page() should be concurrently safe.
>
> AFAICT the only way my mental model is broken is if there is code
> doing a raw get_page() rather than a skb_frag_ref() in core net stack.

Not just. We also get pages fed from the outside, which may be PP pages.
Right now it'd be okay because "from outside" pages would end up in Tx.
Tx always allocates skbs with ->pp_recycle = 0, so we'll hold full refs.

> I would like to get rid of these call sites if they exist. They would
> not interact well with devmem I think (but could be made to work with
> some effort).

Maybe if we convert more code to operate on netmem_ref it will become
clearer where raw pages get fed in, and therefore were we have to be
very careful?