Re: [PATCH v2] kernfs: fix race to increment for nr_mmapped in kernfs_fop_mmap()

Greg Kroah-Hartman <[email protected]> Fri, 31 Jul 2026 13:14:01 +0200
Newsgroups dev.linux.lists.driver-core,org.kernel.vger.linux-kernel
Message-ID <2026073146-condiment-liberty-4b05@gregkh>
On Thu, Jul 30, 2026 at 06:09:12PM -0700, Kevin Mitchell wrote:
> Counts of files to be released (nr_to_release) and mmapped (nr_mmapped)
> files were added to kernfs_open_node in commit bdb2fd7fc56e ("kernfs:
> Skip kernfs_drain_open_files() more aggressively") to optimize
> kernfs_drain_open_files(). A WARN_ON_ONCE sanity check was also added in
> kernfs_drain_open_files() to ensure that these counters were brought to
> zero once all files had been drained.
> 
> Modifications to these counters were protected by kernfs_open_file_mutex
> everywhere except for in kernfs_fop_mmap(). This caused a race condition
> where some nr_mmapped increments could get overwritten even while the
> correct number of kernfs_open_files with mmapped == true were present in
> the kernfs_open_node's files list. Consequently, the iteration in
> kernfs_drain_open_files() would underflow nr_mmapped and the WARNING
> would fire.
> 
> To fix this, acquire kernfs_open_file_mutex around nr_mmapped updates in
> kernfs_fop_mmap.
> 
> The nesting of->mutex -> kernfs_open_file_mutex is safe as
> kernfs_open_file_mutex is acquired last avoiding the possible cycles
> highlighted in commit f83f3c515654 ("kernfs: fix locking around
> kernfs_ops->release() callback").
> 
> Fixes: bdb2fd7fc56e ("kernfs: Skip kernfs_drain_open_files() more aggressively")
> Signed-off-by: Kevin Mitchell <[email protected]>
> ---
> Changes in v2:
> - Rework the approach to use kernfs_open_file_mutex_lock instead of
>   atomics based on feedback from Greg KH.
> - Link to v1: https://lore.kernel.org/all/[email protected]
> 
>  fs/kernfs/file.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c
> index 8e0e90c93372..6f63eb6be1cd 100644
> --- a/fs/kernfs/file.c
> +++ b/fs/kernfs/file.c
> @@ -495,8 +495,12 @@ static int kernfs_fop_mmap(struct file *file, struct vm_area_struct *vma)
>  
>  	rc = 0;
>  	if (!of->mmapped) {
> -		of->mmapped = true;
> +		struct mutex *mutex = kernfs_open_file_mutex_lock(of->kn);
> +
>  		of_on(of)->nr_mmapped++;
> +		mutex_unlock(mutex)
> +;

That line looks very odd, didn't checkpatch catch it?