Skip to content

Commit 29c0636

Browse files
hqsznamjaejeon
authored andcommitted
exfat: combine iocharset and utf8 option setup
Currently, exfat utf8 mount option depends on the iocharset option value. After exfat remount, utf8 option may become inconsistent with iocharset option. If the options are inconsistent; (specifically, iocharset=utf8 but utf8=0) readdir may reference uninitalized NLS, leading to a null pointer dereference. Extract and combine utf8/iocharset setup logic into exfat_set_iocharset(). Then Replace iocharset setup logic to exfat_set_iocharset to prevent utf8/iocharset option inconsistentcy after remount. Reported-by: [email protected] Closes: https://syzkaller.appspot.com/bug?extid=3e9cb93e3c5f90d28e19 Signed-off-by: Sang-Heon Jeon <[email protected]> Fixes: acab02ffcd6b ("exfat: support modifying mount options via remount") Tested-by: [email protected] Reviewed-by: Yuezhang Mo <[email protected]> Signed-off-by: Namjae Jeon <[email protected]>
1 parent e6fd5d3 commit 29c0636

File tree

1 file changed

+15
-9
lines changed

1 file changed

+15
-9
lines changed

fs/exfat/super.c

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ static void exfat_free_iocharset(struct exfat_sb_info *sbi)
3131
kfree(sbi->options.iocharset);
3232
}
3333

34+
static void exfat_set_iocharset(struct exfat_mount_options *opts,
35+
char *iocharset)
36+
{
37+
opts->iocharset = iocharset;
38+
if (!strcmp(opts->iocharset, "utf8"))
39+
opts->utf8 = 1;
40+
else
41+
opts->utf8 = 0;
42+
}
43+
3444
static void exfat_put_super(struct super_block *sb)
3545
{
3646
struct exfat_sb_info *sbi = EXFAT_SB(sb);
@@ -292,7 +302,7 @@ static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param)
292302
break;
293303
case Opt_charset:
294304
exfat_free_iocharset(sbi);
295-
opts->iocharset = param->string;
305+
exfat_set_iocharset(opts, param->string);
296306
param->string = NULL;
297307
break;
298308
case Opt_errors:
@@ -664,8 +674,8 @@ static int exfat_fill_super(struct super_block *sb, struct fs_context *fc)
664674
/* set up enough so that it can read an inode */
665675
exfat_hash_init(sb);
666676

667-
if (!strcmp(sbi->options.iocharset, "utf8"))
668-
opts->utf8 = 1;
677+
if (sbi->options.utf8)
678+
set_default_d_op(sb, &exfat_utf8_dentry_ops);
669679
else {
670680
sbi->nls_io = load_nls(sbi->options.iocharset);
671681
if (!sbi->nls_io) {
@@ -674,12 +684,8 @@ static int exfat_fill_super(struct super_block *sb, struct fs_context *fc)
674684
err = -EINVAL;
675685
goto free_table;
676686
}
677-
}
678-
679-
if (sbi->options.utf8)
680-
set_default_d_op(sb, &exfat_utf8_dentry_ops);
681-
else
682687
set_default_d_op(sb, &exfat_dentry_ops);
688+
}
683689

684690
root_inode = new_inode(sb);
685691
if (!root_inode) {
@@ -809,8 +815,8 @@ static int exfat_init_fs_context(struct fs_context *fc)
809815
sbi->options.fs_fmask = current->fs->umask;
810816
sbi->options.fs_dmask = current->fs->umask;
811817
sbi->options.allow_utime = -1;
812-
sbi->options.iocharset = exfat_default_iocharset;
813818
sbi->options.errors = EXFAT_ERRORS_RO;
819+
exfat_set_iocharset(&sbi->options, exfat_default_iocharset);
814820

815821
fc->s_fs_info = sbi;
816822
fc->ops = &exfat_context_ops;

0 commit comments

Comments
 (0)