Skip to content

Commit 3a78450

Browse files
YuezhangMonamjaejeon
authored andcommitted
exfat: fix appending discontinuous clusters to empty file
Eric Hong found that when using ftruncate to expand an empty file, exfat_ent_set() will fail if discontinuous clusters are allocated. The reason is that the empty file does not have a cluster chain, but exfat_ent_set() attempts to append the newly allocated cluster to the cluster chain. In addition, exfat_find_last_cluster() only supports finding the last cluster in a non-empty file. So this commit adds a check whether the file is empty. If the file is empty, exfat_find_last_cluster() and exfat_ent_set() are no longer called as they do not need to be called. Fixes: f55c096 ("exfat: do not zero the extended part") Reported-by: Eric Hong <[email protected]> Signed-off-by: Yuezhang Mo <[email protected]> Signed-off-by: Namjae Jeon <[email protected]>
1 parent c02197f commit 3a78450

File tree

1 file changed

+22
-15
lines changed

1 file changed

+22
-15
lines changed

fs/exfat/file.c

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,18 @@ static int exfat_cont_expand(struct inode *inode, loff_t size)
3535
if (new_num_clusters == num_clusters)
3636
goto out;
3737

38-
exfat_chain_set(&clu, ei->start_clu, num_clusters, ei->flags);
39-
ret = exfat_find_last_cluster(sb, &clu, &last_clu);
40-
if (ret)
41-
return ret;
38+
if (num_clusters) {
39+
exfat_chain_set(&clu, ei->start_clu, num_clusters, ei->flags);
40+
ret = exfat_find_last_cluster(sb, &clu, &last_clu);
41+
if (ret)
42+
return ret;
43+
44+
clu.dir = last_clu + 1;
45+
} else {
46+
last_clu = EXFAT_EOF_CLUSTER;
47+
clu.dir = EXFAT_EOF_CLUSTER;
48+
}
4249

43-
clu.dir = (last_clu == EXFAT_EOF_CLUSTER) ?
44-
EXFAT_EOF_CLUSTER : last_clu + 1;
4550
clu.size = 0;
4651
clu.flags = ei->flags;
4752

@@ -51,17 +56,19 @@ static int exfat_cont_expand(struct inode *inode, loff_t size)
5156
return ret;
5257

5358
/* Append new clusters to chain */
54-
if (clu.flags != ei->flags) {
55-
exfat_chain_cont_cluster(sb, ei->start_clu, num_clusters);
56-
ei->flags = ALLOC_FAT_CHAIN;
57-
}
58-
if (clu.flags == ALLOC_FAT_CHAIN)
59-
if (exfat_ent_set(sb, last_clu, clu.dir))
60-
goto free_clu;
61-
62-
if (num_clusters == 0)
59+
if (num_clusters) {
60+
if (clu.flags != ei->flags)
61+
if (exfat_chain_cont_cluster(sb, ei->start_clu, num_clusters))
62+
goto free_clu;
63+
64+
if (clu.flags == ALLOC_FAT_CHAIN)
65+
if (exfat_ent_set(sb, last_clu, clu.dir))
66+
goto free_clu;
67+
} else
6368
ei->start_clu = clu.dir;
6469

70+
ei->flags = clu.flags;
71+
6572
out:
6673
inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
6774
/* Expanded range not zeroed, do not update valid_size */

0 commit comments

Comments
 (0)