From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from casper.infradead.org (casper.infradead.org [90.155.50.34]) (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 F15A715E97 for ; Fri, 19 Jun 2026 13:38:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=90.155.50.34 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781876302; cv=none; b=lcFEk/jYH/pApZS7gv7xSY92sM7dFhwXV3DjGBz0pDTgRJ1GKFVen0RIOfVGx/P8g4nMD6qu1pJr9jZB0hB4Yvl1qBRMoMfWpV5j0me9zJozGEjtzeFPLHylYWherBIsiZQJbctNWEK1hTQ+tWkt3aFK9QeIHvZZuJ6t+YHw+TQ= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781876302; c=relaxed/simple; bh=sQSs2CTlkaOQn/Afp6ins9GJXZft7D58cgR7pikD5fA=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=gw7ytJPcb/q46TPFRgrGVuP5R2h6BUzX2MpzowJDEBKscDAAy5I+GK1WOXpxS5J2f+D/j/jaBKaCkOJdfQOMDaklnArmaMIUvcw+geK/RGSAl3q9kjZvPGn/R5fnunb6Sjt/1QUPr7Syzgeg+yNg9eLj1XMZPASDL7Za2tm6oG8= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=infradead.org; spf=pass smtp.mailfrom=infradead.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b=To0I8s1j; arc=none smtp.client-ip=90.155.50.34 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=infradead.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=infradead.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b="To0I8s1j" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=In-Reply-To:Content-Type:MIME-Version: References:Message-ID:Subject:Cc:To:From:Date:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description; bh=BMwaRfaSNig8cK1GvVKyG1ZNglpL5+cdZWNunlOULDQ=; b=To0I8s1jfrFK9OLyjtKYgwtcMs iyArb3g2zZ8KFEBOaJk7YNqG/XUTQYotcN/d8ouwTpYsFaDVQT8VErpSBKdWDiVJHEnPGyb2vL0Rx HsK6hVyAJ5WSdXWpK+GLqf3j+t/aiDZW6HxlOj5g6ZoEjPQnWhiN4vSyHoqNUxi6db8Dw6iWUf9fZ ShJDqyEIwVxAdzWfcnE40PHlSbAE1X0/tK0I6KjsT4ya4YpWeiRSzvN3cITut95THq8d5mLeCJsV+ pmxOOpHH5WpEHZ9x0HQL1pZA2wnvtqH5wksmJOBxh/U3PBLnKuHXJim8jOd5T0PHhbVi3mO8Hb58l Pc742lNQ==; Received: from willy by casper.infradead.org with local (Exim 4.99.1 #2 (Red Hat Linux)) id 1waZQA-0000000GJ8G-1okT; Fri, 19 Jun 2026 13:38:10 +0000 Date: Fri, 19 Jun 2026 14:38:10 +0100 From: Matthew Wilcox To: "David Hildenbrand (Arm)" Cc: Luiz Capitulino , Ketan , Andrew Morton , Vlastimil Babka , Suren Baghdasaryan , Michal Hocko , Brendan Jackman , Johannes Weiner , Zi Yan , kernel@oss.qualcomm.com, linux-mm@kvack.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH] mm: page_ext: validate section in for_each_page_ext iterator Message-ID: References: <20260617-page_ext-v1-1-37ad802b1a38@oss.qualcomm.com> <1dbebf73-6c46-44e1-ac6a-f5ffa9849b37@kernel.org> <698e5cdc-8f1d-4984-bb54-a4b7979b4dc8@redhat.com> <3149fcee-eded-49b0-baf4-ab69c27ff063@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <3149fcee-eded-49b0-baf4-ab69c27ff063@kernel.org> On Fri, Jun 19, 2026 at 10:00:59AM +0200, David Hildenbrand (Arm) wrote: > Likely we should just handle that in the iterator, looking up page-ext for something > that doesn't exist is weird. Yes, but I prefer to pass 'max' to the _next step explicitly, rather than put it in the iterator struct. Untested patch attached. The other way to do it is s/index/remaining/ and count it down rather than upwards. But that assumes none of the iterator users look at iter->index, and I don't have the patience to check that. I find it weird that somebody botheresd to add kernel-doc for page_ext_iter_begin/next. They're internal implementation and really shouldn't have public documentation. diff --git a/include/linux/page_ext.h b/include/linux/page_ext.h index 61e876e255e8..4f7d7a8709de 100644 --- a/include/linux/page_ext.h +++ b/include/linux/page_ext.h @@ -120,14 +120,18 @@ struct page_ext_iter { * page_ext_iter_begin() - Prepare for iterating through page extensions. * @iter: page extension iterator. * @pfn: PFN of the page we're interested in. + * @count: maximum number of page extensions to return. * * Must be called with RCU read lock taken. * * Return: NULL if no page_ext exists for this page. */ static inline struct page_ext *page_ext_iter_begin(struct page_ext_iter *iter, - unsigned long pfn) + unsigned long pfn, unsigned long count) { + if (count == 0) + return NULL; + iter->index = 0; iter->start_pfn = pfn; iter->page_ext = page_ext_lookup(pfn); @@ -138,19 +142,22 @@ static inline struct page_ext *page_ext_iter_begin(struct page_ext_iter *iter, /** * page_ext_iter_next() - Get next page extension * @iter: page extension iterator. + * @count: maximum number of page extensions to return. * * Must be called with RCU read lock taken. * * Return: NULL if no next page_ext exists. */ -static inline struct page_ext *page_ext_iter_next(struct page_ext_iter *iter) +static inline struct page_ext *page_ext_iter_next(struct page_ext_iter *iter, + unsigned long count) { unsigned long pfn; if (WARN_ON_ONCE(!iter->page_ext)) return NULL; - iter->index++; + if (iter->index++ >= count) + return NULL; pfn = iter->start_pfn + iter->index; if (page_ext_iter_next_fast_possible(pfn)) @@ -183,9 +190,9 @@ static inline struct page_ext *page_ext_iter_get(const struct page_ext_iter *ite * IMPORTANT: must be called with RCU read lock taken. */ #define for_each_page_ext(__page, __pgcount, __page_ext, __iter) \ - for (__page_ext = page_ext_iter_begin(&__iter, page_to_pfn(__page));\ - __page_ext && __iter.index < __pgcount; \ - __page_ext = page_ext_iter_next(&__iter)) + for (__page_ext = page_ext_iter_begin(&__iter, page_to_pfn(__page), __pgcount); \ + __page_ext; \ + __page_ext = page_ext_iter_next(&__iter, __pgcount)) #else /* !CONFIG_PAGE_EXTENSION */ struct page_ext;