From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-m121183.xmail.ntesmail.com (mail-m121183.xmail.ntesmail.com [115.236.121.183]) (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 BBD9D3BBFDA for ; Thu, 18 Jun 2026 08:50:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.236.121.183 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781772664; cv=none; b=GT0Xr9F3hsoGsdYFOC3WIuOfDEIVobnbJd0DwuNhcgt4f2DM3Xf+1ccLRqUjG8Uae29bNZsB0aqnmPMLv9d4CErVeOY+aT7oTR4s7lBe4ShJg75pkSuNABpiSYq7TgUgrwHJuNSlt6W5A9O2LIpld+NbElyGjR8J6cFKAKqcGuc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781772664; c=relaxed/simple; bh=KnvrN8ihQJN8xYXKaJKuKfxS70WSaH+tw34VrcPF3gk=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=VIczn+E4HZZ79aqW3VKLVyv6xZKVuoSNcx1+XufNywL2pgtWumZ5S2QhYr/GSM5mozU5YyAIoH1khi7PIy1Nl1RxUuL4ydheXvhGVLpVmLuOv6AP7L0CA27991RBvZ+9qGUXWVHt3YLOH+68Mtlq4jo7uFoCxZhzc9P9x1MW6ro= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=easystack.cn; spf=pass smtp.mailfrom=easystack.cn; arc=none smtp.client-ip=115.236.121.183 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=easystack.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=easystack.cn Received: from [192.168.0.59] (unknown [218.94.118.90]) by smtp.qiye.163.com (Hmail) with ESMTP id 1b9c16d16; Thu, 18 Jun 2026 16:15:24 +0800 (GMT+08:00) Message-ID: <444a6fd9-26dd-4d33-b836-987ef220b5f2@easystack.cn> Date: Thu, 18 Jun 2026 16:15:23 +0800 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 v9 0/4] mm/page_owner: add per-fd filter infrastructure for print_mode and NUMA filtering To: "Vlastimil Babka (SUSE)" , Andrew Morton Cc: surenb@google.com, mhocko@suse.com, jackmanb@google.com, hannes@cmpxchg.org, ziy@nvidia.com, linux-mm@kvack.org, linux-kernel@vger.kernel.org References: <20260525081652.2210206-1-zhen.ni@easystack.cn> <20260525125819.1857f215bc56b26a0727bedc@linux-foundation.org> <5ef656db-c6b6-4a2c-b6be-628e5214952f@easystack.cn> <7b2125bb-c2d6-4678-9ae3-6f4e93034391@kernel.org> From: "zhen.ni" In-Reply-To: <7b2125bb-c2d6-4678-9ae3-6f4e93034391@kernel.org> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit X-HM-Tid: 0a9ed9cc95400229kunmf11eec17f1bec X-HM-MType: 1 X-HM-Spam-Status: e1kfGhgUHx5ZQUpXWQgPGg8OCBgUHx5ZQUlOS1dZFg8aDwILHllBWSg2Ly tZV1koWUFJQjdXWRgWCB1ZQUpXWS1ZQUlXWQ8JGhUIEh9ZQVkZT0wYVktLGUgdGk4fSkgZTlYVFA kWGhdVGRETFhoSFyQUDg9ZV1kYEgtZQVlJSkNVQk9VSkpDVUJLWVdZFhoPEhUdFFlBWU9LSFVCQk lOS1VKS0tVSkJLQlkG 在 2026/6/18 15:27, Vlastimil Babka (SUSE) 写道: > On 6/17/26 10:52, zhen.ni wrote: >> 在 2026/5/26 03:58, Andrew Morton 写道: >>> On Mon, 25 May 2026 16:16:48 +0800 Zhen Ni wrote: >>> >>>> This patch series introduces per-file-descriptor filtering capabilities to the >>>> page_owner feature. >>> >>> Thanks again. AI review has found a bunch of new things to get worried >>> about: >>> https://sashiko.dev/#/patchset/20260525081652.2210206-1-zhen.ni@easystack.cn >>> >>> >> Hi, >> >> Can this lead to an out-of-bounds memory read? >> >> The NUMA filter in page_owner (mm/page_owner.c:790-798) bypasses >> PF_POISONED_CHECK() to avoid triggering VM_BUG_ON during concurrent page >> allocation/free: >> >> int page_nid = memdesc_nid(page->flags); >> >> When NODE_NOT_IN_PAGE_FLAGS is defined, memdesc_nid() performs unchecked >> array access: >> >> int memdesc_nid(memdesc_flags_t mdf) >> { >> return section_to_node_table[memdesc_section(mdf)]; >> } >> >> If page->flags is poisoned, memdesc_section() can return a garbage >> section_nr that causes out-of-bounds access. >> >> ## Lockless Access Safety Principle >> >> The page_owner iterator runs without locks, meaning pages can be >> allocated or freed concurrently. The fundamental design principle should be: >> >> "It's acceptable to skip a small number of abnormal pages, but panics >> must be prevented." >> >> In lockless iteration, TOCTOU is unavoidable - even with reference >> counting or RCU, page->flags can still be modified concurrently during >> access. Zone locks prevent this but are prohibitively expensive. >> >> ## Proposed Solution: Add nid to struct page_owner >> >> Record nid at allocation time when page state is stable, eliminating the >> need to extract it from page->flags during iteration: >> >> ### 1. Modify struct page_owner >> >> struct page_owner { >> unsigned short order; >> short last_migrate_reason; >> ... >> pid_t tgid; >> pid_t free_pid; >> pid_t free_tgid; >> int nid; // NEW >> }; >> >> ### 2. Record nid during allocation >> >> static inline void __update_page_owner_handle(struct page *page, ...) >> { >> int nid = page_to_nid(page); // Safe in allocation context >> >> for_each_page_ext(page, 1 << order, page_ext, iter) { >> page_owner = get_page_owner(page_ext); >> page_owner->nid = nid; >> // ... other fields ... >> } >> } >> >> ### 3. Use saved nid in NUMA filter >> >> if (state->nid_filter_enabled) { >> int page_nid = page_owner->nid; // Direct read, safe >> >> if (!node_isset(page_nid, state->nid_filter)) { >> spin_unlock_irqrestore(&state->lock, flags); >> goto ext_put_continue; >> } >> } >> >> ### 4. Update nid on page migration >> >> // In split_page_owner() when page migrates >> page_owner->nid = page_to_nid(&newfolio->page); >> > > This (presumably LLM) suggestion is a, let's say "lazy" solution to the > problem, leading to more memory usage. I'd be surprised if it's not possible > to read the nid in a way that avoids the hazards. If page_to_nid() can > trigger a VM_BUG_ON(), then I'd add a version without that VM_BUG_ON(), > handling the poisoned state gracefully - if it's poisoned, return e.g. > NUMA_NO_NODE and skip the page, or something. > >> The remaining two issues can also be improved. If there are no >> additional comments, I will proceed with sending v10. >> >> >> Thanks, >> Zhen > > > Thank you for the review. I'd like to clarify that the "nid" member approach was my own design after careful consideration of alternatives, not a suggestion from automated tools.:) In fact, LLMs suggested approaches like "check then access" which I had already implemented and rejected in earlier versions due to TOCTOU issues. The key insight is that page_owner serves as a buffering layer for struct page, eliminating lockless access inconsistency entirely. Think about it this way: Even with extensive checks, page_owner->handle cannot guarantee the page won't be freed when printed. The time window between checking page->flags and accessing page->flags is unavoidable in lockless iteration. By recording nid at allocation time (when page->flags is stable), page_owner becomes a "consistent snapshot" that can be safely accessed without locks. This is the same principle that makes page_owner work as a debug feature in the first place - it accepts a small inconsistency window in exchange for lockless access. Alternative approaches (adding poison checks, bounds checking) cannot fully eliminate TOCTOU in lockless code - they just reduce the probability. The buffering approach is the way to provide both safety and lockless performance. Thanks, Zhen