Linux EXT4 FS development
 help / color / mirror / Atom feed
* Misuse of mapping_set_folio_order_range()
@ 2026-07-27 20:25 Matthew Wilcox
  0 siblings, 0 replies; only message in thread
From: Matthew Wilcox @ 2026-07-27 20:25 UTC (permalink / raw)
  To: linux-ext4
  Cc: Baokun Li, Jan Kara, Zhang Yi, Ojaswin Mujoo, Theodore Ts'o

While reviewing an unrelated change, Sashiko seems to have found a bug
in ext4:

> --- Patch [9]: [PATCH v6 09/12] filemap: Remove checks in mapping_set_folio_order_range() ---
> commit c0859bbb9afcf450bfdee34a144cba981c50e605
> Author: Matthew Wilcox (Oracle) <willy@infradead.org>
> 
> filemap: Remove checks in mapping_set_folio_order_range()
> 
> This commit removes the maximum order checks in mapping_set_folio_order_range()
> to allow its use in hugetlb.
> 
> > diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
> > index 2c3718d592d6d..968b791cfd148 100644
> > --- a/include/linux/pagemap.h
> > +++ b/include/linux/pagemap.h
> > @@ -405,29 +405,23 @@ static inline size_t mapping_max_folio_size_supported(void)
> 
> [ ... ]
> 
> >  static inline void mapping_set_folio_order_range(struct address_space *mapping,
> > -						 unsigned int min,
> > -						 unsigned int max)
> > +		unsigned int min, unsigned int max)
> >  {
> > -	if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
> > +	if (!IS_ENABLED(CONFIG_LARGE_FOLIO))
> >  		return;
> > -
> > -	if (min > MAX_PAGECACHE_ORDER)
> > -		min = MAX_PAGECACHE_ORDER;
> > -
> > -	if (max > MAX_PAGECACHE_ORDER)
> > -		max = MAX_PAGECACHE_ORDER;
> > -
> >  	if (max < min)
> >  		max = min;
> >  
> >  	mapping->flags = (mapping->flags & ~AS_FOLIO_ORDER_MASK) |
> >  		(min << AS_FOLIO_ORDER_MIN) | (max << AS_FOLIO_ORDER_MAX);
> 
> This is a pre-existing issue, but can this non-atomic read-modify-write of
> mapping->flags cause lost updates to concurrently set atomic bit flags?
> 
> While the documentation above this function states it should not be called
> while the inode is active, ext4_change_inode_journal_flag() dynamically
> invokes it on an active inode during the EXT4_IOC_SETFLAGS ioctl:
> 
> fs/ext4/inode.c:ext4_change_inode_journal_flag() {
>     ...
>     ext4_set_inode_mapping_order(inode);
>     ...
> }
> 
> If a privileged user toggles the ext4 journal flag, could this non-atomic
> update race with mm_take_all_locks() (which can be triggered by userfaultfd
> or KVM) modifying AS_MM_ALL_LOCKS via atomic bitops?
> 
> Since they do not share any locks (ext4_change_inode_journal_flag() holds
> inode_lock and invalidate_lock, while mm_take_all_locks() holds mmap_lock
> and i_mmap_rwsem), losing the AS_MM_ALL_LOCKS bit could cause
> vm_unlock_mapping() to skip unlocking mapping->i_mmap_rwsem, resulting in a
> permanent deadlock.

Making mapping_set_folio_order_range() atomic would be a pain -- it'd
involve a cmpxchg() loop which would be utterly useless for most
callers.  Can you figure out how to fix this in ext4?

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-07-27 20:25 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-27 20:25 Misuse of mapping_set_folio_order_range() Matthew Wilcox

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox