From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 68D6428980E for ; Tue, 23 Dec 2025 09:42:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766482972; cv=none; b=B+Z8jt6DobVL1cMCYbUYDxsUHiblE9hxYgf9eQQVXGKS9p3j+Xf5l6gsYLbHR/hofENvvnXEy0Wb2PcieNdL9tNG6YhaIe144RPj7veNJQM47b/IiYT5BQgqjfG0Ao5DuyvJMH2SR7E4DQj3yzL9wZcpGfAG/bUDgEZEcy0vS30= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766482972; c=relaxed/simple; bh=OgrrIS5kSKeOkNAg1o3SBBtI3WjzGuW6Rb6zXIqANak=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=VACc+w7xkAJyEVCsDgBuSzKiIZkw6Nyu0a9KLRFpx+3BvXk+LHU6gUP0p+npcJ0fI1ixG4xEsTnEXcAJhCP4rEcvXsF9rUasCBIqbC5r4LzlsygrBaa0jFlTPNBqpdrg+RIAS0j5w7UjZlgFqBVNOxL4Be+ml4/GOta4csnkWdo= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=HbF7OsaP; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="HbF7OsaP" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8C4F5C113D0; Tue, 23 Dec 2025 09:42:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1766482970; bh=OgrrIS5kSKeOkNAg1o3SBBtI3WjzGuW6Rb6zXIqANak=; h=Date:Subject:To:Cc:References:From:In-Reply-To:From; b=HbF7OsaP13i2azHJQ3dr2a8dsVsPs6XCg8dDvmQY6JaRJZwTNq5LsDRgo2BSZtIn6 Y5jxrvIuZoh9wNQo0XKnraDTCQd73MbY7tMGNY4ETJz4NRtYFMhyr49UXPp5dN/oJD iyDiEikKs4yJxB4R/LlnF8XMNK8EtoljcZfMT9J6CsOnRP3Zd2mHZGirMy0dzj0xiV lnVvfQSOgsF3DAhKZG3Mx5pmsD1dj3zybweckn4H1h0nFiVz4oReiCTFJLWWn0Jwqx XVMRF8i6QZfre+PYKfBLbyIYe2tGzoGj0sTFx103LaDk+Q63pxju9aEwezE42jo09e 38PeAH6+cYZog== Message-ID: Date: Tue, 23 Dec 2025 10:42:44 +0100 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH] mm/page_owner: fix prematurely released rcu_read_lock() To: ranxiaokai627@163.com, akpm@linux-foundation.org, vbabka@suse.cz, surenb@google.com, mhocko@suse.com, jackmanb@google.com, hannes@cmpxchg.org, ziy@nvidia.com, luizcap@redhat.com Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org, ran.xiaokai@zte.com.cn References: <20251223092526.140566-1-ranxiaokai627@163.com> From: "David Hildenbrand (Red Hat)" Content-Language: en-US In-Reply-To: <20251223092526.140566-1-ranxiaokai627@163.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit On 12/23/25 10:25, ranxiaokai627@163.com wrote: > From: Ran Xiaokai > > In CONFIG_SPARSEMEM systems, page_ext uses RCU to synchronize with > memory hotplug operations, ensuring page_ext memory won't be freed > due to MEM_OFFLINE during page_ext data access. > > Since page_owner is part of page_ext, rcu_read_lock() must be held > continuously throughout the entire page_owner access period and > should not be released midway. Otherwise, it may cause the > use-after-free issue. The sequence is like this: > > CPU0 CPU1 > __folio_copy_owner(): MEM_OFFLINE: > page_ext = page_ext_get(&old->page); > old_page_owner = ... > page_ext_put(page_ext); > > page_ext = page_ext_get(&newfolio->page); > new_page_owner = ... > page_ext_put(page_ext); > __invalidate_page_ext(pfn); > synchronize_rcu(); > __free_page_ext(pfn); > old_page_owner->pid > new_page_owner->order ---> access to freed area > > Fixes: 3a812bed3d32a ("mm: page_owner: use new iteration API") > Signed-off-by: Ran Xiaokai > --- > mm/page_owner.c | 21 +++++++++++---------- > 1 file changed, 11 insertions(+), 10 deletions(-) > > diff --git a/mm/page_owner.c b/mm/page_owner.c > index b6a394a130ec..5d6860e54be7 100644 > --- a/mm/page_owner.c > +++ b/mm/page_owner.c > @@ -375,24 +375,25 @@ void __split_page_owner(struct page *page, int old_order, int new_order) > void __folio_copy_owner(struct folio *newfolio, struct folio *old) > { > struct page_ext *page_ext; > + struct page_ext *old_page_ext, *new_page_ext; > struct page_ext_iter iter; > struct page_owner *old_page_owner; > struct page_owner *new_page_owner; > depot_stack_handle_t migrate_handle; > > - page_ext = page_ext_get(&old->page); > - if (unlikely(!page_ext)) > + old_page_ext = page_ext_get(&old->page); > + if (unlikely(!old_page_ext)) > return; > > - old_page_owner = get_page_owner(page_ext); > - page_ext_put(page_ext); > + old_page_owner = get_page_owner(old_page_ext); > > - page_ext = page_ext_get(&newfolio->page); > - if (unlikely(!page_ext)) > + new_page_ext = page_ext_get(&newfolio->page); > + if (unlikely(!new_page_ext)) { > + page_ext_put(old_page_ext); > return; > + } > > - new_page_owner = get_page_owner(page_ext); > - page_ext_put(page_ext); > + new_page_owner = get_page_owner(new_page_ext); > > migrate_handle = new_page_owner->handle; > __update_page_owner_handle(&newfolio->page, old_page_owner->handle, > @@ -414,12 +415,12 @@ void __folio_copy_owner(struct folio *newfolio, struct folio *old) > * for the new one and the old folio otherwise there will be an imbalance > * when subtracting those pages from the stack. > */ > - rcu_read_lock(); > for_each_page_ext(&old->page, 1 << new_page_owner->order, page_ext, iter) { > old_page_owner = get_page_owner(page_ext); > old_page_owner->handle = migrate_handle; > } > - rcu_read_unlock(); > + page_ext_put(new_page_ext); > + page_ext_put(old_page_ext); > } How are you possibly able to call into __split_page_owner() while concurrently we are already finished with offlining the memory (-> all memory freed and isolated in the buddy) and triggering the notifier? Doesn't make sense, no? -- Cheers David