* [RFC] mm/huge_memory: prevent potential NULL pointer dereference @ 2025-07-16 14:58 Antonio Quartulli 2025-07-16 15:07 ` Lorenzo Stoakes 2025-07-16 15:10 ` Zi Yan 0 siblings, 2 replies; 10+ messages in thread From: Antonio Quartulli @ 2025-07-16 14:58 UTC (permalink / raw) To: linux-mm Cc: Antonio Quartulli, Andrew Morton, David Hildenbrand, Lorenzo Stoakes, Baolin Wang, Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Zi Yan I just found this issue in the last linux-next Coverity report and it caught my attention. I am not familiar with this code, therefore I am sending this patch as RFC because I am not 100% sure whether this is a false positive or not. However, it seems potentially legit to me: In __folio_split(), when looping over folios we dereference `mapping` before ensuring it is non-NULL. Following code in the loop body performs such check, thus suggesting that `mapping` may be NULL and accessing it without any check may be dangerous. Add NULL check before passing it to shmem_mapping(). Cc: Zi Yan <ziy@nvidia.com> Fixes: 00527733d0dc ("mm/huge_memory: add two new (not yet used) functions for folio_split()") Addresses-Coverity-ID: 1647614 ("FORWARD_NULL") Signed-off-by: Antonio Quartulli <antonio@mandelbit.com> --- mm/huge_memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 389620c65a5f..d649026db95a 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3802,7 +3802,7 @@ static int __folio_split(struct folio *folio, unsigned int new_order, /* Some pages can be beyond EOF: drop them from cache */ if (new_folio->index >= end) { - if (shmem_mapping(mapping)) + if (mapping && shmem_mapping(mapping)) nr_shmem_dropped += folio_nr_pages(new_folio); else if (folio_test_clear_dirty(new_folio)) folio_account_cleaned( -- 2.49.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [RFC] mm/huge_memory: prevent potential NULL pointer dereference 2025-07-16 14:58 [RFC] mm/huge_memory: prevent potential NULL pointer dereference Antonio Quartulli @ 2025-07-16 15:07 ` Lorenzo Stoakes 2025-07-16 19:05 ` Antonio Quartulli 2025-07-16 15:10 ` Zi Yan 1 sibling, 1 reply; 10+ messages in thread From: Lorenzo Stoakes @ 2025-07-16 15:07 UTC (permalink / raw) To: Antonio Quartulli Cc: linux-mm, Andrew Morton, David Hildenbrand, Baolin Wang, Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Zi Yan On Wed, Jul 16, 2025 at 04:58:04PM +0200, Antonio Quartulli wrote: > I just found this issue in the last linux-next Coverity report and it > caught my attention. > I am not familiar with this code, therefore I am sending this patch > as RFC because I am not 100% sure whether this is a false positive or > not. > However, it seems potentially legit to me: > > In __folio_split(), when looping over folios we dereference > `mapping` before ensuring it is non-NULL. > > Following code in the loop body performs such check, thus > suggesting that `mapping` may be NULL and accessing it > without any check may be dangerous. > > Add NULL check before passing it to shmem_mapping(). > > Cc: Zi Yan <ziy@nvidia.com> > Fixes: 00527733d0dc ("mm/huge_memory: add two new (not yet used) functions for folio_split()") > Addresses-Coverity-ID: 1647614 ("FORWARD_NULL") > Signed-off-by: Antonio Quartulli <antonio@mandelbit.com> Thanks for the patch :) but sorry it is in practice not a thing that can happen. See below for analysis. > --- > mm/huge_memory.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/mm/huge_memory.c b/mm/huge_memory.c > index 389620c65a5f..d649026db95a 100644 > --- a/mm/huge_memory.c > +++ b/mm/huge_memory.c > @@ -3802,7 +3802,7 @@ static int __folio_split(struct folio *folio, unsigned int new_order, > > /* Some pages can be beyond EOF: drop them from cache */ > if (new_folio->index >= end) { It's kind of not _hugely_ clear but, if anon - which implies no mapping - we set end == -1. At which point this condition cannot evaluate true (index is at page granularity so even MAX_UINT64 would be page shifted and still not equal -1). Under all other circumstances, mapping will be non-NULL. > - if (shmem_mapping(mapping)) > + if (mapping && shmem_mapping(mapping)) > nr_shmem_dropped += folio_nr_pages(new_folio); > else if (folio_test_clear_dirty(new_folio)) > folio_account_cleaned( > -- > 2.49.1 > > Cheers, Lorenzo ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC] mm/huge_memory: prevent potential NULL pointer dereference 2025-07-16 15:07 ` Lorenzo Stoakes @ 2025-07-16 19:05 ` Antonio Quartulli 2025-07-16 19:10 ` Lorenzo Stoakes 0 siblings, 1 reply; 10+ messages in thread From: Antonio Quartulli @ 2025-07-16 19:05 UTC (permalink / raw) To: Lorenzo Stoakes Cc: linux-mm, Andrew Morton, David Hildenbrand, Baolin Wang, Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Zi Yan Hi Lorenzo, On 16/07/2025 17:07, Lorenzo Stoakes wrote: >> diff --git a/mm/huge_memory.c b/mm/huge_memory.c >> index 389620c65a5f..d649026db95a 100644 >> --- a/mm/huge_memory.c >> +++ b/mm/huge_memory.c >> @@ -3802,7 +3802,7 @@ static int __folio_split(struct folio *folio, unsigned int new_order, >> >> /* Some pages can be beyond EOF: drop them from cache */ >> if (new_folio->index >= end) { > > It's kind of not _hugely_ clear but, if anon - which implies no mapping - we set > end == -1. > > At which point this condition cannot evaluate true (index is at page granularity > so even MAX_UINT64 would be page shifted and still not equal -1). I may be missing something, but why can't "index >= -1" be true? In any case, with Zi's patch the NULL check comes before the rest so the problem does not exist anymore there. Regards, > > Under all other circumstances, mapping will be non-NULL. > >> - if (shmem_mapping(mapping)) >> + if (mapping && shmem_mapping(mapping)) >> nr_shmem_dropped += folio_nr_pages(new_folio); >> else if (folio_test_clear_dirty(new_folio)) >> folio_account_cleaned( >> -- >> 2.49.1 >> >> > > Cheers, Lorenzo -- Antonio Quartulli CEO and Co-Founder Mandelbit Srl https://www.mandelbit.com ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC] mm/huge_memory: prevent potential NULL pointer dereference 2025-07-16 19:05 ` Antonio Quartulli @ 2025-07-16 19:10 ` Lorenzo Stoakes 2025-07-16 19:13 ` Antonio Quartulli 0 siblings, 1 reply; 10+ messages in thread From: Lorenzo Stoakes @ 2025-07-16 19:10 UTC (permalink / raw) To: Antonio Quartulli Cc: linux-mm, Andrew Morton, David Hildenbrand, Baolin Wang, Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Zi Yan On Wed, Jul 16, 2025 at 09:05:14PM +0200, Antonio Quartulli wrote: > Hi Lorenzo, > > On 16/07/2025 17:07, Lorenzo Stoakes wrote: > > > diff --git a/mm/huge_memory.c b/mm/huge_memory.c > > > index 389620c65a5f..d649026db95a 100644 > > > --- a/mm/huge_memory.c > > > +++ b/mm/huge_memory.c > > > @@ -3802,7 +3802,7 @@ static int __folio_split(struct folio *folio, unsigned int new_order, > > > > > > /* Some pages can be beyond EOF: drop them from cache */ > > > if (new_folio->index >= end) { > > > > It's kind of not _hugely_ clear but, if anon - which implies no mapping - we set > > end == -1. > > > > At which point this condition cannot evaluate true (index is at page granularity > > so even MAX_UINT64 would be page shifted and still not equal -1). > > I may be missing something, but why can't "index >= -1" be true? These are unsigned long's, -1 in two's complement this means -1 translates to the maximum possible unsigned long. Index cannot == the maximum number as this is a _page_ index so a folio would need to reference a page larger than could be represented in a 64-bit system for that to be so. > > In any case, with Zi's patch the NULL check comes before the rest so the > problem does not exist anymore there. > > Regards, > > > > > Under all other circumstances, mapping will be non-NULL. > > > > > - if (shmem_mapping(mapping)) > > > + if (mapping && shmem_mapping(mapping)) > > > nr_shmem_dropped += folio_nr_pages(new_folio); > > > else if (folio_test_clear_dirty(new_folio)) > > > folio_account_cleaned( > > > -- > > > 2.49.1 > > > > > > > > > > Cheers, Lorenzo > > -- > Antonio Quartulli > > CEO and Co-Founder > Mandelbit Srl > https://www.mandelbit.com > > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC] mm/huge_memory: prevent potential NULL pointer dereference 2025-07-16 19:10 ` Lorenzo Stoakes @ 2025-07-16 19:13 ` Antonio Quartulli 0 siblings, 0 replies; 10+ messages in thread From: Antonio Quartulli @ 2025-07-16 19:13 UTC (permalink / raw) To: Lorenzo Stoakes Cc: linux-mm, Andrew Morton, David Hildenbrand, Baolin Wang, Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Zi Yan On 16/07/2025 21:10, Lorenzo Stoakes wrote: > On Wed, Jul 16, 2025 at 09:05:14PM +0200, Antonio Quartulli wrote: >> Hi Lorenzo, >> >> On 16/07/2025 17:07, Lorenzo Stoakes wrote: >>>> diff --git a/mm/huge_memory.c b/mm/huge_memory.c >>>> index 389620c65a5f..d649026db95a 100644 >>>> --- a/mm/huge_memory.c >>>> +++ b/mm/huge_memory.c >>>> @@ -3802,7 +3802,7 @@ static int __folio_split(struct folio *folio, unsigned int new_order, >>>> >>>> /* Some pages can be beyond EOF: drop them from cache */ >>>> if (new_folio->index >= end) { >>> >>> It's kind of not _hugely_ clear but, if anon - which implies no mapping - we set >>> end == -1. >>> >>> At which point this condition cannot evaluate true (index is at page granularity >>> so even MAX_UINT64 would be page shifted and still not equal -1). >> >> I may be missing something, but why can't "index >= -1" be true? > > These are unsigned long's, -1 in two's complement this means -1 translates > to the maximum possible unsigned long. Index cannot == the maximum number > as this is a _page_ index so a folio would need to reference a page larger > than could be represented in a 64-bit system for that to be so. Got it! Thanks a lot for the clarification. Cheers, -- Antonio Quartulli CEO and Co-Founder Mandelbit Srl https://www.mandelbit.com ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC] mm/huge_memory: prevent potential NULL pointer dereference 2025-07-16 14:58 [RFC] mm/huge_memory: prevent potential NULL pointer dereference Antonio Quartulli 2025-07-16 15:07 ` Lorenzo Stoakes @ 2025-07-16 15:10 ` Zi Yan 2025-07-16 15:18 ` David Hildenbrand 2025-07-16 16:18 ` Dan Carpenter 1 sibling, 2 replies; 10+ messages in thread From: Zi Yan @ 2025-07-16 15:10 UTC (permalink / raw) To: Antonio Quartulli Cc: linux-mm, Andrew Morton, David Hildenbrand, Lorenzo Stoakes, Baolin Wang, Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Dan Carpenter On 16 Jul 2025, at 10:58, Antonio Quartulli wrote: > I just found this issue in the last linux-next Coverity report and it > caught my attention. > I am not familiar with this code, therefore I am sending this patch > as RFC because I am not 100% sure whether this is a false positive or > not. > However, it seems potentially legit to me: > > In __folio_split(), when looping over folios we dereference > `mapping` before ensuring it is non-NULL. > > Following code in the loop body performs such check, thus > suggesting that `mapping` may be NULL and accessing it > without any check may be dangerous. > > Add NULL check before passing it to shmem_mapping(). > > Cc: Zi Yan <ziy@nvidia.com> > Fixes: 00527733d0dc ("mm/huge_memory: add two new (not yet used) functions for folio_split()") > Addresses-Coverity-ID: 1647614 ("FORWARD_NULL") > Signed-off-by: Antonio Quartulli <antonio@mandelbit.com> > --- > mm/huge_memory.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/mm/huge_memory.c b/mm/huge_memory.c > index 389620c65a5f..d649026db95a 100644 > --- a/mm/huge_memory.c > +++ b/mm/huge_memory.c > @@ -3802,7 +3802,7 @@ static int __folio_split(struct folio *folio, unsigned int new_order, > > /* Some pages can be beyond EOF: drop them from cache */ > if (new_folio->index >= end) { > - if (shmem_mapping(mapping)) > + if (mapping && shmem_mapping(mapping)) > nr_shmem_dropped += folio_nr_pages(new_folio); > else if (folio_test_clear_dirty(new_folio)) > folio_account_cleaned( Hi Antonio, Is there a way of preventing Coverity/sparse from checking certain code? This non-NULL mapping issue pops up every time I touch the code. Dan Carpenter reported the issue yesterday and I explained it is no issue[1]. The same report showed up when I added __split_unmapped_folio() back in February[2] [1] https://lore.kernel.org/oe-kbuild/64b54034-f311-4e7d-b935-c16775dbb642@suswa.mountain/ [2] https://lore.kernel.org/linux-mm/2afe3d59-aca5-40f7-82a3-a6d976fb0f4f@stanley.mountain/ I wonder how many times I need to explain this, although I appreciate your effort to improve kernel. Best Regards, Yan, Zi ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC] mm/huge_memory: prevent potential NULL pointer dereference 2025-07-16 15:10 ` Zi Yan @ 2025-07-16 15:18 ` David Hildenbrand 2025-07-16 15:24 ` Zi Yan 2025-07-16 16:18 ` Dan Carpenter 1 sibling, 1 reply; 10+ messages in thread From: David Hildenbrand @ 2025-07-16 15:18 UTC (permalink / raw) To: Zi Yan, Antonio Quartulli Cc: linux-mm, Andrew Morton, Lorenzo Stoakes, Baolin Wang, Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Dan Carpenter On 16.07.25 17:10, Zi Yan wrote: > On 16 Jul 2025, at 10:58, Antonio Quartulli wrote: > >> I just found this issue in the last linux-next Coverity report and it >> caught my attention. >> I am not familiar with this code, therefore I am sending this patch >> as RFC because I am not 100% sure whether this is a false positive or >> not. >> However, it seems potentially legit to me: >> >> In __folio_split(), when looping over folios we dereference >> `mapping` before ensuring it is non-NULL. >> >> Following code in the loop body performs such check, thus >> suggesting that `mapping` may be NULL and accessing it >> without any check may be dangerous. >> >> Add NULL check before passing it to shmem_mapping(). >> >> Cc: Zi Yan <ziy@nvidia.com> >> Fixes: 00527733d0dc ("mm/huge_memory: add two new (not yet used) functions for folio_split()") >> Addresses-Coverity-ID: 1647614 ("FORWARD_NULL") >> Signed-off-by: Antonio Quartulli <antonio@mandelbit.com> >> --- >> mm/huge_memory.c | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/mm/huge_memory.c b/mm/huge_memory.c >> index 389620c65a5f..d649026db95a 100644 >> --- a/mm/huge_memory.c >> +++ b/mm/huge_memory.c >> @@ -3802,7 +3802,7 @@ static int __folio_split(struct folio *folio, unsigned int new_order, >> >> /* Some pages can be beyond EOF: drop them from cache */ >> if (new_folio->index >= end) { >> - if (shmem_mapping(mapping)) >> + if (mapping && shmem_mapping(mapping)) >> nr_shmem_dropped += folio_nr_pages(new_folio); >> else if (folio_test_clear_dirty(new_folio)) >> folio_account_cleaned( > Hi Antonio, > > Is there a way of preventing Coverity/sparse from checking certain code? > This non-NULL mapping issue pops up every time I touch the code. Probably we could make that code more readable and achieve it: diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 24aff14d22a1e..acf56aae1a2ef 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -3775,6 +3775,7 @@ static int __folio_split(struct folio *folio, unsigned int new_order, */ for (new_folio = folio_next(folio); new_folio != next_folio; new_folio = next) { + unsigned long nr_pages = folio_nr_pages(new_folio); next = folio_next(new_folio); expected_refs = folio_expected_ref_count(new_folio) + 1; @@ -3782,20 +3783,20 @@ static int __folio_split(struct folio *folio, unsigned int new_order, lru_add_split_folio(folio, new_folio, lruvec, list); - /* Some pages can be beyond EOF: drop them from cache */ - if (new_folio->index >= end) { - if (shmem_mapping(mapping)) - nr_shmem_dropped += folio_nr_pages(new_folio); - else if (folio_test_clear_dirty(new_folio)) - folio_account_cleaned( - new_folio, - inode_to_wb(mapping->host)); - __filemap_remove_folio(new_folio, NULL); - folio_put_refs(new_folio, - folio_nr_pages(new_folio)); - } else if (mapping) { - __xa_store(&mapping->i_pages, new_folio->index, - new_folio, 0); + /* Add the new folio to the page cache ... */ + if (mapping) { + /* ... however, drop folios beyond EOF. */ + if (new_folio->index >= end) { + if (shmem_mapping(mapping)) + nr_shmem_dropped += nr_pages; + else if (folio_test_clear_dirty(new_folio)) + folio_account_cleaned(new_folio, inode_to_wb(mapping->host)); + __filemap_remove_folio(new_folio, NULL); + folio_put_refs(new_folio, nr_pages); + } else { + __xa_store(&mapping->i_pages, + new_folio->index, new_folio, 0); + } } else if (swap_cache) { __xa_store(&swap_cache->i_pages, swap_cache_index(new_folio->swap), Having that logic in a helper would be cleaner, but not straight-forward due to things like nr_shmem_dropped. -- Cheers, David / dhildenb ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [RFC] mm/huge_memory: prevent potential NULL pointer dereference 2025-07-16 15:18 ` David Hildenbrand @ 2025-07-16 15:24 ` Zi Yan 2025-07-16 15:31 ` David Hildenbrand 0 siblings, 1 reply; 10+ messages in thread From: Zi Yan @ 2025-07-16 15:24 UTC (permalink / raw) To: David Hildenbrand Cc: Antonio Quartulli, linux-mm, Andrew Morton, Lorenzo Stoakes, Baolin Wang, Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Dan Carpenter On 16 Jul 2025, at 11:18, David Hildenbrand wrote: > On 16.07.25 17:10, Zi Yan wrote: >> On 16 Jul 2025, at 10:58, Antonio Quartulli wrote: >> >>> I just found this issue in the last linux-next Coverity report and it >>> caught my attention. >>> I am not familiar with this code, therefore I am sending this patch >>> as RFC because I am not 100% sure whether this is a false positive or >>> not. >>> However, it seems potentially legit to me: >>> >>> In __folio_split(), when looping over folios we dereference >>> `mapping` before ensuring it is non-NULL. >>> >>> Following code in the loop body performs such check, thus >>> suggesting that `mapping` may be NULL and accessing it >>> without any check may be dangerous. >>> >>> Add NULL check before passing it to shmem_mapping(). >>> >>> Cc: Zi Yan <ziy@nvidia.com> >>> Fixes: 00527733d0dc ("mm/huge_memory: add two new (not yet used) functions for folio_split()") >>> Addresses-Coverity-ID: 1647614 ("FORWARD_NULL") >>> Signed-off-by: Antonio Quartulli <antonio@mandelbit.com> >>> --- >>> mm/huge_memory.c | 2 +- >>> 1 file changed, 1 insertion(+), 1 deletion(-) >>> >>> diff --git a/mm/huge_memory.c b/mm/huge_memory.c >>> index 389620c65a5f..d649026db95a 100644 >>> --- a/mm/huge_memory.c >>> +++ b/mm/huge_memory.c >>> @@ -3802,7 +3802,7 @@ static int __folio_split(struct folio *folio, unsigned int new_order, >>> >>> /* Some pages can be beyond EOF: drop them from cache */ >>> if (new_folio->index >= end) { >>> - if (shmem_mapping(mapping)) >>> + if (mapping && shmem_mapping(mapping)) >>> nr_shmem_dropped += folio_nr_pages(new_folio); >>> else if (folio_test_clear_dirty(new_folio)) >>> folio_account_cleaned( >> Hi Antonio, >> >> Is there a way of preventing Coverity/sparse from checking certain code? >> This non-NULL mapping issue pops up every time I touch the code. > > Probably we could make that code more readable and achieve it: > > diff --git a/mm/huge_memory.c b/mm/huge_memory.c > index 24aff14d22a1e..acf56aae1a2ef 100644 > --- a/mm/huge_memory.c > +++ b/mm/huge_memory.c > @@ -3775,6 +3775,7 @@ static int __folio_split(struct folio *folio, unsigned int new_order, > */ > for (new_folio = folio_next(folio); new_folio != next_folio; > new_folio = next) { > + unsigned long nr_pages = folio_nr_pages(new_folio); > next = folio_next(new_folio); > expected_refs = folio_expected_ref_count(new_folio) + 1; > @@ -3782,20 +3783,20 @@ static int __folio_split(struct folio *folio, unsigned int new_order, > lru_add_split_folio(folio, new_folio, lruvec, list); > - /* Some pages can be beyond EOF: drop them from cache */ > - if (new_folio->index >= end) { > - if (shmem_mapping(mapping)) > - nr_shmem_dropped += folio_nr_pages(new_folio); > - else if (folio_test_clear_dirty(new_folio)) > - folio_account_cleaned( > - new_folio, > - inode_to_wb(mapping->host)); > - __filemap_remove_folio(new_folio, NULL); > - folio_put_refs(new_folio, > - folio_nr_pages(new_folio)); > - } else if (mapping) { > - __xa_store(&mapping->i_pages, new_folio->index, > - new_folio, 0); > + /* Add the new folio to the page cache ... */ > + if (mapping) { > + /* ... however, drop folios beyond EOF. */ > + if (new_folio->index >= end) { > + if (shmem_mapping(mapping)) > + nr_shmem_dropped += nr_pages; > + else if (folio_test_clear_dirty(new_folio)) > + folio_account_cleaned(new_folio, inode_to_wb(mapping->host)); > + __filemap_remove_folio(new_folio, NULL); > + folio_put_refs(new_folio, nr_pages); > + } else { > + __xa_store(&mapping->i_pages, > + new_folio->index, new_folio, 0); > + } > } else if (swap_cache) { > __xa_store(&swap_cache->i_pages, > swap_cache_index(new_folio->swap), > > > Having that logic in a helper would be cleaner, but not straight-forward due > to things like nr_shmem_dropped. Looks good to me. Do you want to send a patch? Otherwise, I can send one. Best Regards, Yan, Zi ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC] mm/huge_memory: prevent potential NULL pointer dereference 2025-07-16 15:24 ` Zi Yan @ 2025-07-16 15:31 ` David Hildenbrand 0 siblings, 0 replies; 10+ messages in thread From: David Hildenbrand @ 2025-07-16 15:31 UTC (permalink / raw) To: Zi Yan Cc: Antonio Quartulli, linux-mm, Andrew Morton, Lorenzo Stoakes, Baolin Wang, Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Dan Carpenter On 16.07.25 17:24, Zi Yan wrote: > On 16 Jul 2025, at 11:18, David Hildenbrand wrote: > >> On 16.07.25 17:10, Zi Yan wrote: >>> On 16 Jul 2025, at 10:58, Antonio Quartulli wrote: >>> >>>> I just found this issue in the last linux-next Coverity report and it >>>> caught my attention. >>>> I am not familiar with this code, therefore I am sending this patch >>>> as RFC because I am not 100% sure whether this is a false positive or >>>> not. >>>> However, it seems potentially legit to me: >>>> >>>> In __folio_split(), when looping over folios we dereference >>>> `mapping` before ensuring it is non-NULL. >>>> >>>> Following code in the loop body performs such check, thus >>>> suggesting that `mapping` may be NULL and accessing it >>>> without any check may be dangerous. >>>> >>>> Add NULL check before passing it to shmem_mapping(). >>>> >>>> Cc: Zi Yan <ziy@nvidia.com> >>>> Fixes: 00527733d0dc ("mm/huge_memory: add two new (not yet used) functions for folio_split()") >>>> Addresses-Coverity-ID: 1647614 ("FORWARD_NULL") >>>> Signed-off-by: Antonio Quartulli <antonio@mandelbit.com> >>>> --- >>>> mm/huge_memory.c | 2 +- >>>> 1 file changed, 1 insertion(+), 1 deletion(-) >>>> >>>> diff --git a/mm/huge_memory.c b/mm/huge_memory.c >>>> index 389620c65a5f..d649026db95a 100644 >>>> --- a/mm/huge_memory.c >>>> +++ b/mm/huge_memory.c >>>> @@ -3802,7 +3802,7 @@ static int __folio_split(struct folio *folio, unsigned int new_order, >>>> >>>> /* Some pages can be beyond EOF: drop them from cache */ >>>> if (new_folio->index >= end) { >>>> - if (shmem_mapping(mapping)) >>>> + if (mapping && shmem_mapping(mapping)) >>>> nr_shmem_dropped += folio_nr_pages(new_folio); >>>> else if (folio_test_clear_dirty(new_folio)) >>>> folio_account_cleaned( >>> Hi Antonio, >>> >>> Is there a way of preventing Coverity/sparse from checking certain code? >>> This non-NULL mapping issue pops up every time I touch the code. >> >> Probably we could make that code more readable and achieve it: >> >> diff --git a/mm/huge_memory.c b/mm/huge_memory.c >> index 24aff14d22a1e..acf56aae1a2ef 100644 >> --- a/mm/huge_memory.c >> +++ b/mm/huge_memory.c >> @@ -3775,6 +3775,7 @@ static int __folio_split(struct folio *folio, unsigned int new_order, >> */ >> for (new_folio = folio_next(folio); new_folio != next_folio; >> new_folio = next) { >> + unsigned long nr_pages = folio_nr_pages(new_folio); >> next = folio_next(new_folio); >> expected_refs = folio_expected_ref_count(new_folio) + 1; >> @@ -3782,20 +3783,20 @@ static int __folio_split(struct folio *folio, unsigned int new_order, >> lru_add_split_folio(folio, new_folio, lruvec, list); >> - /* Some pages can be beyond EOF: drop them from cache */ >> - if (new_folio->index >= end) { >> - if (shmem_mapping(mapping)) >> - nr_shmem_dropped += folio_nr_pages(new_folio); >> - else if (folio_test_clear_dirty(new_folio)) >> - folio_account_cleaned( >> - new_folio, >> - inode_to_wb(mapping->host)); >> - __filemap_remove_folio(new_folio, NULL); >> - folio_put_refs(new_folio, >> - folio_nr_pages(new_folio)); >> - } else if (mapping) { >> - __xa_store(&mapping->i_pages, new_folio->index, >> - new_folio, 0); >> + /* Add the new folio to the page cache ... */ >> + if (mapping) { >> + /* ... however, drop folios beyond EOF. */ >> + if (new_folio->index >= end) { >> + if (shmem_mapping(mapping)) >> + nr_shmem_dropped += nr_pages; >> + else if (folio_test_clear_dirty(new_folio)) >> + folio_account_cleaned(new_folio, inode_to_wb(mapping->host)); >> + __filemap_remove_folio(new_folio, NULL); >> + folio_put_refs(new_folio, nr_pages); >> + } else { >> + __xa_store(&mapping->i_pages, >> + new_folio->index, new_folio, 0); >> + } >> } else if (swap_cache) { >> __xa_store(&swap_cache->i_pages, >> swap_cache_index(new_folio->swap), >> >> >> Having that logic in a helper would be cleaner, but not straight-forward due >> to things like nr_shmem_dropped. > > Looks good to me. Do you want to send a patch? Otherwise, I can send one. Please send on (you'll manage to clean this up further). Thanks! -- Cheers, David / dhildenb ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC] mm/huge_memory: prevent potential NULL pointer dereference 2025-07-16 15:10 ` Zi Yan 2025-07-16 15:18 ` David Hildenbrand @ 2025-07-16 16:18 ` Dan Carpenter 1 sibling, 0 replies; 10+ messages in thread From: Dan Carpenter @ 2025-07-16 16:18 UTC (permalink / raw) To: Zi Yan Cc: Antonio Quartulli, linux-mm, Andrew Morton, David Hildenbrand, Lorenzo Stoakes, Baolin Wang, Liam R. Howlett, Nico Pache, Ryan Roberts, Dev Jain, Barry Song On Wed, Jul 16, 2025 at 11:10:00AM -0400, Zi Yan wrote: > On 16 Jul 2025, at 10:58, Antonio Quartulli wrote: > > > I just found this issue in the last linux-next Coverity report and it > > caught my attention. > > I am not familiar with this code, therefore I am sending this patch > > as RFC because I am not 100% sure whether this is a false positive or > > not. > > However, it seems potentially legit to me: > > > > In __folio_split(), when looping over folios we dereference > > `mapping` before ensuring it is non-NULL. > > > > Following code in the loop body performs such check, thus > > suggesting that `mapping` may be NULL and accessing it > > without any check may be dangerous. > > > > Add NULL check before passing it to shmem_mapping(). > > > > Cc: Zi Yan <ziy@nvidia.com> > > Fixes: 00527733d0dc ("mm/huge_memory: add two new (not yet used) functions for folio_split()") > > Addresses-Coverity-ID: 1647614 ("FORWARD_NULL") > > Signed-off-by: Antonio Quartulli <antonio@mandelbit.com> > > --- > > mm/huge_memory.c | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > diff --git a/mm/huge_memory.c b/mm/huge_memory.c > > index 389620c65a5f..d649026db95a 100644 > > --- a/mm/huge_memory.c > > +++ b/mm/huge_memory.c > > @@ -3802,7 +3802,7 @@ static int __folio_split(struct folio *folio, unsigned int new_order, > > > > /* Some pages can be beyond EOF: drop them from cache */ > > if (new_folio->index >= end) { > > - if (shmem_mapping(mapping)) > > + if (mapping && shmem_mapping(mapping)) > > nr_shmem_dropped += folio_nr_pages(new_folio); > > else if (folio_test_clear_dirty(new_folio)) > > folio_account_cleaned( > Hi Antonio, > > Is there a way of preventing Coverity/sparse from checking certain code? > This non-NULL mapping issue pops up every time I touch the code. > > Dan Carpenter reported the issue yesterday and I explained it is no issue[1]. > The same report showed up when I added __split_unmapped_folio() > back in February[2] > > [1] https://lore.kernel.org/oe-kbuild/64b54034-f311-4e7d-b935-c16775dbb642@suswa.mountain/ > [2] https://lore.kernel.org/linux-mm/2afe3d59-aca5-40f7-82a3-a6d976fb0f4f@stanley.mountain/ > > I wonder how many times I need to explain this, although I appreciate > your effort to improve kernel. The way to disable static analysis is to wrap the line or function in #ifndef __CHECKER__. This is a bad option. We could probably count how many places do this using one set of fingers and toes. We don't like defines in .c files. I hate when static analysis makes the code messier and worse. We always say to fix the checker and leave the code alone. We generally try to only report warnings once, but in this case you changed the name of the function so it shows up as new. All the scripts say if you change the name of the file or the function that's a new warning. When I'm searching for duplicate reports on lore, I use the name of the function as well. Plus, I looked at the surrounding code and everything on my screen was from Jul 7 so I assumed it was new. The best option is to add a comment to the code. The next best option is to just endure the occasional false positive. One idea might be to add a hash tag to static checker warnings/patches so we can manually search lore.kernel.org for the filename and hash tag before sending new bug reports/fixes. regards, dan carpenter ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2025-07-16 19:13 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-07-16 14:58 [RFC] mm/huge_memory: prevent potential NULL pointer dereference Antonio Quartulli 2025-07-16 15:07 ` Lorenzo Stoakes 2025-07-16 19:05 ` Antonio Quartulli 2025-07-16 19:10 ` Lorenzo Stoakes 2025-07-16 19:13 ` Antonio Quartulli 2025-07-16 15:10 ` Zi Yan 2025-07-16 15:18 ` David Hildenbrand 2025-07-16 15:24 ` Zi Yan 2025-07-16 15:31 ` David Hildenbrand 2025-07-16 16:18 ` Dan Carpenter
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).