nilfs2 updates for v7.2

- nilfs2: Fix return in nilfs_mkdir
 - nilfs2: fix backing_dev_info reference leak
 - nilfs2: reject CLEAN_SEGMENTS ioctl with out-of-range segment numbers
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQT4wVoLCG92poNnMFAhI4xTh21NnQUCai99EgAKCRAhI4xTh21N
 nbR2APwJtTMFdg9c4fdCcDauoP2uvDhG08/DfQBhMHBlqbWuBQEAw0f7gLJ6EJQG
 7pZ7g2/SEdK/Obm3fzoemteACklYPgg=
 =22JG
 -----END PGP SIGNATURE-----

Merge tag 'nilfs2-v7.2-tag1' of git://git.kernel.org/pub/scm/linux/kernel/git/vdubeyko/nilfs2

Pull nilfs2 updates from Viacheslav Dubeyko:
 "Fixes of syzbot reported issue and various small fixes in NILFS2
  functionality.

   - fix hung task in nilfs_transaction_begin() (Deepanshu Kartikey)

     Reported by syzbot. The root cause is that user-supplied segment
     numbers were not validated before nilfs_clean_segments() began
     doing work; the range check on each segnum was performed deep
     inside the call chain by nilfs_sufile_updatev(), which emits a
     nilfs_warn() per invalid entry while still holding the segctor lock
     and the sufile mi_sem.

     Fix it by validating the contents of kbufs[4] in
     nilfs_clean_segments() immediately after acquiring ns_segctor_sem
     via nilfs_transaction_lock().

   - fix a smatch warning in nilfs_mkdir() warn (Hongling Zeng)

     This corrects a semantic issue related to the use of the
     ERR_PTR macro that arose from a recent VFS change.

   - fix a backing_dev_info reference leak (Shuangpeng Bai)

     setup_bdev_super() initializes sb->s_bdev and takes a reference on
     the block device backing_dev_info when assigning sb->s_bdi.

     nilfs_fill_super() takes another reference to the same
     backing_dev_info and stores it in sb->s_bdi again. The extra
     reference is not paired with a matching bdi_put(), since
     generic_shutdown_super() releases sb->s_bdi only once.

     Drop the redundant bdi_get() in nilfs_fill_super(). The single
     reference taken by setup_bdev_super() is enough and is released
     during superblock shutdown"

* tag 'nilfs2-v7.2-tag1' of git://git.kernel.org/pub/scm/linux/kernel/git/vdubeyko/nilfs2:
  nilfs2: Fix return in nilfs_mkdir
  nilfs2: fix backing_dev_info reference leak
  nilfs2: reject CLEAN_SEGMENTS ioctl with out-of-range segment numbers
This commit is contained in:
Linus Torvalds 2026-06-16 12:14:20 +05:30
commit 6f60a6033c
3 changed files with 23 additions and 3 deletions

View File

@ -258,7 +258,7 @@ static struct dentry *nilfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
else
nilfs_transaction_abort(dir->i_sb);
return ERR_PTR(err);
return err ? ERR_PTR(err) : NULL;
out_fail:
drop_nlink(inode);

View File

@ -2512,12 +2512,33 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,
struct nilfs_sc_info *sci = nilfs->ns_writer;
struct nilfs_transaction_info ti;
int err;
size_t i, nfreesegs = argv[4].v_nmembs;
__u64 *segnumv = kbufs[4];
if (unlikely(!sci))
return -EROFS;
nilfs_transaction_lock(sb, &ti, 1);
/*
* Validate segment numbers under ns_segctor_sem (held for write
* by nilfs_transaction_lock above) so the check is serialized
* against nilfs_ioctl_resize(), which can modify ns_nsegments.
* Rejecting bad input here, before any segment-cleaning work
* begins, avoids the per-element diagnostic path inside
* nilfs_sufile_updatev() that would otherwise run under this
* same lock and stall concurrent readers.
*/
for (i = 0; i < nfreesegs; i++) {
if (segnumv[i] >= nilfs->ns_nsegments) {
nilfs_err(sb,
"Segment number %llu to be freed is out of range",
(unsigned long long)segnumv[i]);
err = -EINVAL;
goto bail_unlock;
}
}
err = nilfs_mdt_save_to_shadow_map(nilfs->ns_dat);
if (unlikely(err))
goto out_unlock;
@ -2558,6 +2579,7 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,
sci->sc_freesegs = NULL;
sci->sc_nfreesegs = 0;
nilfs_mdt_clear_shadow_map(nilfs->ns_dat);
bail_unlock:
nilfs_transaction_unlock(sb);
return err;
}

View File

@ -1070,8 +1070,6 @@ nilfs_fill_super(struct super_block *sb, struct fs_context *fc)
sb->s_time_gran = 1;
sb->s_max_links = NILFS_LINK_MAX;
sb->s_bdi = bdi_get(sb->s_bdev->bd_disk->bdi);
err = load_nilfs(nilfs, sb);
if (err)
goto failed_nilfs;