Skip to content

Commit

Permalink
udf: fix potential refcnt problem of nls module
Browse files Browse the repository at this point in the history
When specifiying iocharset multiple times in a mount or once/multiple in
a remount, current option parsing may cause inaccurate refcount of nls
module.  Also, in the failure cleanup of option parsing, the condition
of calling unload_nls is not sufficient.

Signed-off-by: Chengguang Xu <[email protected]>
Signed-off-by: Jan Kara <[email protected]>
  • Loading branch information
Chengguang Xu authored and jankara committed Mar 2, 2018
1 parent d090990 commit 785dffe
Showing 1 changed file with 10 additions and 5 deletions.
15 changes: 10 additions & 5 deletions fs/udf/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,6 @@ static int udf_parse_options(char *options, struct udf_options *uopt,
uopt->session = 0xFFFFFFFF;
uopt->lastblock = 0;
uopt->anchor = 0;
uopt->nls_map = NULL;

if (!options)
return 1;
Expand Down Expand Up @@ -575,8 +574,12 @@ static int udf_parse_options(char *options, struct udf_options *uopt,
break;
#ifdef CONFIG_UDF_NLS
case Opt_iocharset:
uopt->nls_map = load_nls(args[0].from);
uopt->flags |= (1 << UDF_FLAG_NLS_MAP);
if (!remount) {
if (uopt->nls_map)
unload_nls(uopt->nls_map);
uopt->nls_map = load_nls(args[0].from);
uopt->flags |= (1 << UDF_FLAG_NLS_MAP);
}
break;
#endif
case Opt_uforget:
Expand Down Expand Up @@ -627,6 +630,7 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options)
uopt.umask = sbi->s_umask;
uopt.fmode = sbi->s_fmode;
uopt.dmode = sbi->s_dmode;
uopt.nls_map = NULL;

if (!udf_parse_options(options, &uopt, true))
return -EINVAL;
Expand Down Expand Up @@ -2095,6 +2099,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
uopt.umask = 0;
uopt.fmode = UDF_INVALID_MODE;
uopt.dmode = UDF_INVALID_MODE;
uopt.nls_map = NULL;

sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
if (!sbi)
Expand Down Expand Up @@ -2275,8 +2280,8 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
iput(sbi->s_vat_inode);
parse_options_failure:
#ifdef CONFIG_UDF_NLS
if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
unload_nls(sbi->s_nls_map);
if (uopt.nls_map)
unload_nls(uopt.nls_map);
#endif
if (lvid_open)
udf_close_lvid(sb);
Expand Down

0 comments on commit 785dffe

Please sign in to comment.