Skip to content

Commit 6f60a60

Browse files
committed
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
2 parents 31b706d + e5925f3 commit 6f60a60

3 files changed

Lines changed: 23 additions & 3 deletions

File tree

fs/nilfs2/namei.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ static struct dentry *nilfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
258258
else
259259
nilfs_transaction_abort(dir->i_sb);
260260

261-
return ERR_PTR(err);
261+
return err ? ERR_PTR(err) : NULL;
262262

263263
out_fail:
264264
drop_nlink(inode);

fs/nilfs2/segment.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2512,12 +2512,33 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,
25122512
struct nilfs_sc_info *sci = nilfs->ns_writer;
25132513
struct nilfs_transaction_info ti;
25142514
int err;
2515+
size_t i, nfreesegs = argv[4].v_nmembs;
2516+
__u64 *segnumv = kbufs[4];
25152517

25162518
if (unlikely(!sci))
25172519
return -EROFS;
25182520

25192521
nilfs_transaction_lock(sb, &ti, 1);
25202522

2523+
/*
2524+
* Validate segment numbers under ns_segctor_sem (held for write
2525+
* by nilfs_transaction_lock above) so the check is serialized
2526+
* against nilfs_ioctl_resize(), which can modify ns_nsegments.
2527+
* Rejecting bad input here, before any segment-cleaning work
2528+
* begins, avoids the per-element diagnostic path inside
2529+
* nilfs_sufile_updatev() that would otherwise run under this
2530+
* same lock and stall concurrent readers.
2531+
*/
2532+
for (i = 0; i < nfreesegs; i++) {
2533+
if (segnumv[i] >= nilfs->ns_nsegments) {
2534+
nilfs_err(sb,
2535+
"Segment number %llu to be freed is out of range",
2536+
(unsigned long long)segnumv[i]);
2537+
err = -EINVAL;
2538+
goto bail_unlock;
2539+
}
2540+
}
2541+
25212542
err = nilfs_mdt_save_to_shadow_map(nilfs->ns_dat);
25222543
if (unlikely(err))
25232544
goto out_unlock;
@@ -2558,6 +2579,7 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,
25582579
sci->sc_freesegs = NULL;
25592580
sci->sc_nfreesegs = 0;
25602581
nilfs_mdt_clear_shadow_map(nilfs->ns_dat);
2582+
bail_unlock:
25612583
nilfs_transaction_unlock(sb);
25622584
return err;
25632585
}

fs/nilfs2/super.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,8 +1070,6 @@ nilfs_fill_super(struct super_block *sb, struct fs_context *fc)
10701070
sb->s_time_gran = 1;
10711071
sb->s_max_links = NILFS_LINK_MAX;
10721072

1073-
sb->s_bdi = bdi_get(sb->s_bdev->bd_disk->bdi);
1074-
10751073
err = load_nilfs(nilfs, sb);
10761074
if (err)
10771075
goto failed_nilfs;

0 commit comments

Comments
 (0)