Skip to content

Commit 5998f2b

Browse files
committed
Merge tag 'exfat-for-6.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/exfat
Pull exfat updates from Namjae Jeon: - Use generic_write_sync instead of vfs_fsync_range in exfat_file_write_iter. It will fix an issue where fdatasync would be set incorrectly. - Fix potential infinite loop by the self-linked chain. * tag 'exfat-for-6.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/exfat: exfat: add cluster chain loop check for dir exfat: fdatasync flag should be same like generic_write_sync()
2 parents da23ea1 + 99f9a97 commit 5998f2b

File tree

5 files changed

+50
-14
lines changed

5 files changed

+50
-14
lines changed

fs/exfat/dir.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,7 @@ int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei,
996996
struct exfat_hint_femp candi_empty;
997997
struct exfat_sb_info *sbi = EXFAT_SB(sb);
998998
int num_entries = exfat_calc_num_entries(p_uniname);
999+
unsigned int clu_count = 0;
9991000

10001001
if (num_entries < 0)
10011002
return num_entries;
@@ -1133,6 +1134,10 @@ int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei,
11331134
} else {
11341135
if (exfat_get_next_cluster(sb, &clu.dir))
11351136
return -EIO;
1137+
1138+
/* break if the cluster chain includes a loop */
1139+
if (unlikely(++clu_count > EXFAT_DATA_CLUSTER_COUNT(sbi)))
1140+
goto not_found;
11361141
}
11371142
}
11381143

@@ -1195,6 +1200,7 @@ int exfat_count_dir_entries(struct super_block *sb, struct exfat_chain *p_dir)
11951200
int i, count = 0;
11961201
int dentries_per_clu;
11971202
unsigned int entry_type;
1203+
unsigned int clu_count = 0;
11981204
struct exfat_chain clu;
11991205
struct exfat_dentry *ep;
12001206
struct exfat_sb_info *sbi = EXFAT_SB(sb);
@@ -1227,6 +1233,12 @@ int exfat_count_dir_entries(struct super_block *sb, struct exfat_chain *p_dir)
12271233
} else {
12281234
if (exfat_get_next_cluster(sb, &(clu.dir)))
12291235
return -EIO;
1236+
1237+
if (unlikely(++clu_count > sbi->used_clusters)) {
1238+
exfat_fs_error(sb, "FAT or bitmap is corrupted");
1239+
return -EIO;
1240+
}
1241+
12301242
}
12311243
}
12321244

fs/exfat/fatent.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,5 +490,15 @@ int exfat_count_num_clusters(struct super_block *sb,
490490
}
491491

492492
*ret_count = count;
493+
494+
/*
495+
* since exfat_count_used_clusters() is not called, sbi->used_clusters
496+
* cannot be used here.
497+
*/
498+
if (unlikely(i == sbi->num_clusters && clu != EXFAT_EOF_CLUSTER)) {
499+
exfat_fs_error(sb, "The cluster chain has a loop");
500+
return -EIO;
501+
}
502+
493503
return 0;
494504
}

fs/exfat/file.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -622,9 +622,8 @@ static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter)
622622
if (pos > valid_size)
623623
pos = valid_size;
624624

625-
if (iocb_is_dsync(iocb) && iocb->ki_pos > pos) {
626-
ssize_t err = vfs_fsync_range(file, pos, iocb->ki_pos - 1,
627-
iocb->ki_flags & IOCB_SYNC);
625+
if (iocb->ki_pos > pos) {
626+
ssize_t err = generic_write_sync(iocb, iocb->ki_pos - pos);
628627
if (err < 0)
629628
return err;
630629
}

fs/exfat/namei.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -890,6 +890,7 @@ static int exfat_check_dir_empty(struct super_block *sb,
890890
{
891891
int i, dentries_per_clu;
892892
unsigned int type;
893+
unsigned int clu_count = 0;
893894
struct exfat_chain clu;
894895
struct exfat_dentry *ep;
895896
struct exfat_sb_info *sbi = EXFAT_SB(sb);
@@ -926,6 +927,10 @@ static int exfat_check_dir_empty(struct super_block *sb,
926927
} else {
927928
if (exfat_get_next_cluster(sb, &(clu.dir)))
928929
return -EIO;
930+
931+
/* break if the cluster chain includes a loop */
932+
if (unlikely(++clu_count > EXFAT_DATA_CLUSTER_COUNT(sbi)))
933+
break;
929934
}
930935
}
931936

fs/exfat/super.c

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -341,13 +341,12 @@ static void exfat_hash_init(struct super_block *sb)
341341
INIT_HLIST_HEAD(&sbi->inode_hashtable[i]);
342342
}
343343

344-
static int exfat_read_root(struct inode *inode)
344+
static int exfat_read_root(struct inode *inode, struct exfat_chain *root_clu)
345345
{
346346
struct super_block *sb = inode->i_sb;
347347
struct exfat_sb_info *sbi = EXFAT_SB(sb);
348348
struct exfat_inode_info *ei = EXFAT_I(inode);
349-
struct exfat_chain cdir;
350-
int num_subdirs, num_clu = 0;
349+
int num_subdirs;
351350

352351
exfat_chain_set(&ei->dir, sbi->root_dir, 0, ALLOC_FAT_CHAIN);
353352
ei->entry = -1;
@@ -360,12 +359,9 @@ static int exfat_read_root(struct inode *inode)
360359
ei->hint_stat.clu = sbi->root_dir;
361360
ei->hint_femp.eidx = EXFAT_HINT_NONE;
362361

363-
exfat_chain_set(&cdir, sbi->root_dir, 0, ALLOC_FAT_CHAIN);
364-
if (exfat_count_num_clusters(sb, &cdir, &num_clu))
365-
return -EIO;
366-
i_size_write(inode, num_clu << sbi->cluster_size_bits);
362+
i_size_write(inode, EXFAT_CLU_TO_B(root_clu->size, sbi));
367363

368-
num_subdirs = exfat_count_dir_entries(sb, &cdir);
364+
num_subdirs = exfat_count_dir_entries(sb, root_clu);
369365
if (num_subdirs < 0)
370366
return -EIO;
371367
set_nlink(inode, num_subdirs + EXFAT_MIN_SUBDIR);
@@ -578,7 +574,8 @@ static int exfat_verify_boot_region(struct super_block *sb)
578574
}
579575

580576
/* mount the file system volume */
581-
static int __exfat_fill_super(struct super_block *sb)
577+
static int __exfat_fill_super(struct super_block *sb,
578+
struct exfat_chain *root_clu)
582579
{
583580
int ret;
584581
struct exfat_sb_info *sbi = EXFAT_SB(sb);
@@ -595,6 +592,18 @@ static int __exfat_fill_super(struct super_block *sb)
595592
goto free_bh;
596593
}
597594

595+
/*
596+
* Call exfat_count_num_cluster() before searching for up-case and
597+
* bitmap directory entries to avoid infinite loop if they are missing
598+
* and the cluster chain includes a loop.
599+
*/
600+
exfat_chain_set(root_clu, sbi->root_dir, 0, ALLOC_FAT_CHAIN);
601+
ret = exfat_count_num_clusters(sb, root_clu, &root_clu->size);
602+
if (ret) {
603+
exfat_err(sb, "failed to count the number of clusters in root");
604+
goto free_bh;
605+
}
606+
598607
ret = exfat_create_upcase_table(sb);
599608
if (ret) {
600609
exfat_err(sb, "failed to load upcase table");
@@ -627,6 +636,7 @@ static int exfat_fill_super(struct super_block *sb, struct fs_context *fc)
627636
struct exfat_sb_info *sbi = sb->s_fs_info;
628637
struct exfat_mount_options *opts = &sbi->options;
629638
struct inode *root_inode;
639+
struct exfat_chain root_clu;
630640
int err;
631641

632642
if (opts->allow_utime == (unsigned short)-1)
@@ -645,7 +655,7 @@ static int exfat_fill_super(struct super_block *sb, struct fs_context *fc)
645655
sb->s_time_min = EXFAT_MIN_TIMESTAMP_SECS;
646656
sb->s_time_max = EXFAT_MAX_TIMESTAMP_SECS;
647657

648-
err = __exfat_fill_super(sb);
658+
err = __exfat_fill_super(sb, &root_clu);
649659
if (err) {
650660
exfat_err(sb, "failed to recognize exfat type");
651661
goto check_nls_io;
@@ -680,7 +690,7 @@ static int exfat_fill_super(struct super_block *sb, struct fs_context *fc)
680690

681691
root_inode->i_ino = EXFAT_ROOT_INO;
682692
inode_set_iversion(root_inode, 1);
683-
err = exfat_read_root(root_inode);
693+
err = exfat_read_root(root_inode, &root_clu);
684694
if (err) {
685695
exfat_err(sb, "failed to initialize root inode");
686696
goto put_inode;

0 commit comments

Comments
 (0)