KCSAN reports a data race between page_cache_delete() and folio_mapping(): page_cache_delete() performs a plain store to folio->mapping: folio->mapping = NULL; folio_mapping() performs a plain load from folio->mapping: mapping = folio->mapping; page_cache_delete() is called from the truncation path under the i_pages xarray lock, while folio_mapping() is called from the reclaim path (evict_folios -> folio_evictable -> folio_mapping) under only rcu_read_lock() without the xarray lock. The race is benign since the reclaim path tolerates stale values -- reading a stale non-NULL mapping simply results in a suboptimal eviction decision. However, the plain accesses risk store/load tearing and allow the compiler to perform harmful optimizations (merging, elision, or fission of the accesses). Fix this by using WRITE_ONCE() in page_cache_delete() and READ_ONCE() in folio_mapping() to prevent compiler misbehavior and silence the KCSAN report. Fixes: 2f52578f9c64 ("mm/util: Add folio_mapping() and folio_file_mapping()") Reported-by: syzbot+606f94dfeaaa45124c90@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=606f94dfeaaa45124c90 Signed-off-by: Abhishek Kumar --- mm/filemap.c | 2 +- mm/util.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mm/filemap.c b/mm/filemap.c index 406cef06b684..bba669bd114f 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -142,7 +142,7 @@ static void page_cache_delete(struct address_space *mapping, xas_store(&xas, shadow); xas_init_marks(&xas); - folio->mapping = NULL; + WRITE_ONCE(folio->mapping, NULL); /* Leave folio->index set: truncation lookup relies upon it */ mapping->nrpages -= nr; } diff --git a/mm/util.c b/mm/util.c index b05ab6f97e11..5ecb19ddf026 100644 --- a/mm/util.c +++ b/mm/util.c @@ -700,7 +700,7 @@ struct address_space *folio_mapping(const struct folio *folio) if (unlikely(folio_test_swapcache(folio))) return swap_address_space(folio->swap); - mapping = folio->mapping; + mapping = READ_ONCE(folio->mapping); if ((unsigned long)mapping & FOLIO_MAPPING_FLAGS) return NULL; -- 2.43.0