Skip to content

Commit 8170a99

Browse files
committed
Merge tag 'exfat-for-6.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/exfat
Pull exfat updates from Namjae Jeon: - If the start cluster of stream entry is invalid, treat it as the empty directory - Valid size of steam entry cannot be greater than data size. If valid_size is invalid, use data_size - Move Direct-IO alignment check to before extending the valid size - Fix uninit-value issue reported by syzbot - Optimize finding directory entry-set in write_inode, rename, unlink * tag 'exfat-for-6.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/exfat: exfat: reduce FAT chain traversal exfat: code cleanup for exfat_readdir() exfat: remove argument 'p_dir' from exfat_add_entry() exfat: move exfat_chain_set() out of __exfat_resolve_path() exfat: add exfat_get_dentry_set_by_ei() helper exfat: rename argument name for exfat_move_file and exfat_rename_file exfat: remove unnecessary read entry in __exfat_rename() exfat: fix file being changed by unaligned direct write exfat: fix uninit-value in __exfat_get_dentry_set exfat: fix out-of-bounds access of directory entries
2 parents b86545e + 8a3f571 commit 8170a99

File tree

5 files changed

+113
-128
lines changed

5 files changed

+113
-128
lines changed

fs/exfat/dir.c

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,8 @@ static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_ent
8282
if (ei->type != TYPE_DIR)
8383
return -EPERM;
8484

85-
if (ei->entry == -1)
86-
exfat_chain_set(&dir, sbi->root_dir, 0, ALLOC_FAT_CHAIN);
87-
else
88-
exfat_chain_set(&dir, ei->start_clu,
89-
EXFAT_B_TO_CLU(i_size_read(inode), sbi), ei->flags);
85+
exfat_chain_set(&dir, ei->start_clu,
86+
EXFAT_B_TO_CLU(i_size_read(inode), sbi), ei->flags);
9087

9188
dentries_per_clu = sbi->dentries_per_clu;
9289
max_dentries = (unsigned int)min_t(u64, MAX_EXFAT_DENTRIES,
@@ -135,21 +132,6 @@ static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_ent
135132

136133
num_ext = ep->dentry.file.num_ext;
137134
dir_entry->attr = le16_to_cpu(ep->dentry.file.attr);
138-
exfat_get_entry_time(sbi, &dir_entry->crtime,
139-
ep->dentry.file.create_tz,
140-
ep->dentry.file.create_time,
141-
ep->dentry.file.create_date,
142-
ep->dentry.file.create_time_cs);
143-
exfat_get_entry_time(sbi, &dir_entry->mtime,
144-
ep->dentry.file.modify_tz,
145-
ep->dentry.file.modify_time,
146-
ep->dentry.file.modify_date,
147-
ep->dentry.file.modify_time_cs);
148-
exfat_get_entry_time(sbi, &dir_entry->atime,
149-
ep->dentry.file.access_tz,
150-
ep->dentry.file.access_time,
151-
ep->dentry.file.access_date,
152-
0);
153135

154136
*uni_name.name = 0x0;
155137
err = exfat_get_uniname_from_ext_entry(sb, &clu, i,
@@ -166,9 +148,8 @@ static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_ent
166148
ep = exfat_get_dentry(sb, &clu, i + 1, &bh);
167149
if (!ep)
168150
return -EIO;
169-
dir_entry->size =
170-
le64_to_cpu(ep->dentry.stream.valid_size);
171-
dir_entry->entry = dentry;
151+
dir_entry->entry = i;
152+
dir_entry->dir = clu;
172153
brelse(bh);
173154

174155
ei->hint_bmap.off = EXFAT_DEN_TO_CLU(dentry, sbi);
@@ -276,7 +257,7 @@ static int exfat_iterate(struct file *file, struct dir_context *ctx)
276257
if (!nb->lfn[0])
277258
goto end_of_dir;
278259

279-
i_pos = ((loff_t)ei->start_clu << 32) | (de.entry & 0xffffffff);
260+
i_pos = ((loff_t)de.dir.dir << 32) | (de.entry & 0xffffffff);
280261
tmp = exfat_iget(sb, i_pos);
281262
if (tmp) {
282263
inum = tmp->i_ino;

fs/exfat/exfat_fs.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,9 @@ struct exfat_entry_set_cache {
204204
#define IS_DYNAMIC_ES(es) ((es)->__bh != (es)->bh)
205205

206206
struct exfat_dir_entry {
207+
/* the cluster where file dentry is located */
207208
struct exfat_chain dir;
209+
/* the index of file dentry in ->dir */
208210
int entry;
209211
unsigned int type;
210212
unsigned int start_clu;
@@ -290,7 +292,9 @@ struct exfat_sb_info {
290292
* EXFAT file system inode in-memory data
291293
*/
292294
struct exfat_inode_info {
295+
/* the cluster where file dentry is located */
293296
struct exfat_chain dir;
297+
/* the index of file dentry in ->dir */
294298
int entry;
295299
unsigned int type;
296300
unsigned short attr;
@@ -508,6 +512,8 @@ struct exfat_dentry *exfat_get_dentry_cached(struct exfat_entry_set_cache *es,
508512
int exfat_get_dentry_set(struct exfat_entry_set_cache *es,
509513
struct super_block *sb, struct exfat_chain *p_dir, int entry,
510514
unsigned int num_entries);
515+
#define exfat_get_dentry_set_by_ei(es, sb, ei) \
516+
exfat_get_dentry_set(es, sb, &(ei)->dir, (ei)->entry, ES_ALL_ENTRIES)
511517
int exfat_get_empty_dentry_set(struct exfat_entry_set_cache *es,
512518
struct super_block *sb, struct exfat_chain *p_dir, int entry,
513519
unsigned int num_entries);

fs/exfat/file.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,16 @@ static ssize_t exfat_file_write_iter(struct kiocb *iocb, struct iov_iter *iter)
584584
if (ret < 0)
585585
goto unlock;
586586

587+
if (iocb->ki_flags & IOCB_DIRECT) {
588+
unsigned long align = pos | iov_iter_alignment(iter);
589+
590+
if (!IS_ALIGNED(align, i_blocksize(inode)) &&
591+
!IS_ALIGNED(align, bdev_logical_block_size(inode->i_sb->s_bdev))) {
592+
ret = -EINVAL;
593+
goto unlock;
594+
}
595+
}
596+
587597
if (pos > valid_size) {
588598
ret = exfat_extend_valid_size(file, pos);
589599
if (ret < 0 && ret != -ENOSPC) {

fs/exfat/inode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ int __exfat_write_inode(struct inode *inode, int sync)
4343
exfat_set_volume_dirty(sb);
4444

4545
/* get the directory entry of given file or directory */
46-
if (exfat_get_dentry_set(&es, sb, &(ei->dir), ei->entry, ES_ALL_ENTRIES))
46+
if (exfat_get_dentry_set_by_ei(&es, sb, ei))
4747
return -EIO;
4848
ep = exfat_get_dentry_cached(&es, ES_IDX_FILE);
4949
ep2 = exfat_get_dentry_cached(&es, ES_IDX_STREAM);

0 commit comments

Comments
 (0)