All of lore.kernel.org
 help / color / mirror / Atom feed
From: syzbot <syzbot+62edf7e27b2e8f754525@syzkaller.appspotmail.com>
To: kartikey406@gmail.com
Cc: kartikey406@gmail.com, linux-kernel@vger.kernel.org,
	 syzkaller-bugs@googlegroups.com
Subject: Re: [PATCH] hugetlbfs: fix lock imbalance in hugetlb_vmdelete_list
Date: Wed, 24 Sep 2025 23:18:53 -0700	[thread overview]
Message-ID: <68d4decd.050a0220.25d7ab.0000.GAE@google.com> (raw)
In-Reply-To: <20250925061845.1276501-1-kartikey406@gmail.com>

> #syz test: git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master

"git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git" does not look like a valid git repo address.

>
> hugetlb_vmdelete_list() has a lock imbalance bug where lock acquisition
> and release evaluate VMA conditions at different times, potentially
> causing unlock to be called on the wrong lock or skipped entirely.
>
> The current code evaluates __vma_shareable_lock() and __vma_private_lock()
> twice - once during hugetlb_vma_trylock_write() and again during
> hugetlb_vma_unlock_write(). If VMA state changes between these calls
> (due to unmap operations or concurrent access), the lock and unlock
> paths may diverge, leading to:
>
> 1. Unlocking a lock that was never acquired
> 2. Unlocking the wrong lock type
> 3. Leaving a lock held
>
> This manifests as "bad unlock balance detected" warnings:
>
>   WARNING: bad unlock balance detected!
>   trying to release lock (&vma_lock->rw_sema) at:
>   hugetlb_vmdelete_list+0x179/0x1c0 fs/hugetlbfs/inode.c:501
>   but there are no more locks to release!
>
> Fix this by saving the lock type and pointer when acquiring the lock,
> then using the saved information for unlock, ensuring symmetric lock
> operations regardless of any VMA state changes.
>
> Reported-by: syzbot+62edf7e27b2e8f754525@syzkaller.appspotmail.com
> Link: https://syzkaller.appspot.com/bug?extid=62edf7e27b2e8f754525
> Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
> ---
>  fs/hugetlbfs/inode.c | 32 +++++++++++++++++++++++++++++---
>  1 file changed, 29 insertions(+), 3 deletions(-)
>
> diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
> index 9e0625167517..2721ba2ee3f3 100644
> --- a/fs/hugetlbfs/inode.c
> +++ b/fs/hugetlbfs/inode.c
> @@ -42,6 +42,10 @@
>  #define CREATE_TRACE_POINTS
>  #include <trace/events/hugetlbfs.h>
>  
> +#define HPAGE_RESV_OWNER    (1UL << 0)
> +#define HPAGE_RESV_UNMAPPED (1UL << 1)
> +#define HPAGE_RESV_MASK (HPAGE_RESV_OWNER | HPAGE_RESV_UNMAPPED)
> +
>  static const struct address_space_operations hugetlbfs_aops;
>  static const struct file_operations hugetlbfs_file_operations;
>  static const struct inode_operations hugetlbfs_dir_inode_operations;
> @@ -475,6 +479,9 @@ hugetlb_vmdelete_list(struct rb_root_cached *root, pgoff_t start, pgoff_t end,
>  		      zap_flags_t zap_flags)
>  {
>  	struct vm_area_struct *vma;
> +	struct hugetlb_vma_lock *vma_lock;
> +	struct resv_map *resv_map;
> +	bool locked;
>  
>  	/*
>  	 * end == 0 indicates that the entire range after start should be
> @@ -484,8 +491,24 @@ hugetlb_vmdelete_list(struct rb_root_cached *root, pgoff_t start, pgoff_t end,
>  	vma_interval_tree_foreach(vma, root, start, end ? end - 1 : ULONG_MAX) {
>  		unsigned long v_start;
>  		unsigned long v_end;
> -
> -		if (!hugetlb_vma_trylock_write(vma))
> +		vma_lock = NULL;
> +		resv_map = NULL;
> +		locked = false;
> +
> +		if (__vma_shareable_lock(vma)) {
> +			vma_lock = vma->vm_private_data;
> +			if (vma_lock && down_write_trylock(&vma_lock->rw_sema))
> +				locked = true;
> +		} else if (__vma_private_lock(vma)) {
> +			resv_map = (struct resv_map *)((unsigned long)vma->vm_private_data & ~HPAGE_RESV_MASK);
> +			if (resv_map && down_write_trylock(&resv_map->rw_sema))
> +				locked = true;
> +		} else {
> +			/* No lock needed for this VMA */
> +			locked = true;
> +		}
> +
> +		if (!locked)
>  			continue;
>  
>  		v_start = vma_offset_start(vma, start);
> @@ -498,7 +521,10 @@ hugetlb_vmdelete_list(struct rb_root_cached *root, pgoff_t start, pgoff_t end,
>  		 * vmas.  Therefore, lock is not held when calling
>  		 * unmap_hugepage_range for private vmas.
>  		 */
> -		hugetlb_vma_unlock_write(vma);
> +		if (vma_lock)
> +			up_write(&vma_lock->rw_sema);
> +		else if (resv_map)
> +			up_write(&resv_map->rw_sema);
>  	}
>  }
>  
> -- 
> 2.43.0
>

           reply	other threads:[~2025-09-25  6:18 UTC|newest]

Thread overview: expand[flat|nested]  mbox.gz  Atom feed
 [parent not found: <20250925061845.1276501-1-kartikey406@gmail.com>]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=68d4decd.050a0220.25d7ab.0000.GAE@google.com \
    --to=syzbot+62edf7e27b2e8f754525@syzkaller.appspotmail.com \
    --cc=kartikey406@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=syzkaller-bugs@googlegroups.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.