udf: fix potential refcnt problem of nls module
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 <cgxu519@icloud.com> Signed-off-by: Jan Kara <jack@suse.cz>
This commit is contained in:
parent
d090990510
commit
785dffe1da
|
@ -477,7 +477,6 @@ static int udf_parse_options(char *options, struct udf_options *uopt,
|
||||||
uopt->session = 0xFFFFFFFF;
|
uopt->session = 0xFFFFFFFF;
|
||||||
uopt->lastblock = 0;
|
uopt->lastblock = 0;
|
||||||
uopt->anchor = 0;
|
uopt->anchor = 0;
|
||||||
uopt->nls_map = NULL;
|
|
||||||
|
|
||||||
if (!options)
|
if (!options)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -575,8 +574,12 @@ static int udf_parse_options(char *options, struct udf_options *uopt,
|
||||||
break;
|
break;
|
||||||
#ifdef CONFIG_UDF_NLS
|
#ifdef CONFIG_UDF_NLS
|
||||||
case Opt_iocharset:
|
case Opt_iocharset:
|
||||||
uopt->nls_map = load_nls(args[0].from);
|
if (!remount) {
|
||||||
uopt->flags |= (1 << UDF_FLAG_NLS_MAP);
|
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;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case Opt_uforget:
|
case Opt_uforget:
|
||||||
|
@ -627,6 +630,7 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options)
|
||||||
uopt.umask = sbi->s_umask;
|
uopt.umask = sbi->s_umask;
|
||||||
uopt.fmode = sbi->s_fmode;
|
uopt.fmode = sbi->s_fmode;
|
||||||
uopt.dmode = sbi->s_dmode;
|
uopt.dmode = sbi->s_dmode;
|
||||||
|
uopt.nls_map = NULL;
|
||||||
|
|
||||||
if (!udf_parse_options(options, &uopt, true))
|
if (!udf_parse_options(options, &uopt, true))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -2095,6 +2099,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
|
||||||
uopt.umask = 0;
|
uopt.umask = 0;
|
||||||
uopt.fmode = UDF_INVALID_MODE;
|
uopt.fmode = UDF_INVALID_MODE;
|
||||||
uopt.dmode = UDF_INVALID_MODE;
|
uopt.dmode = UDF_INVALID_MODE;
|
||||||
|
uopt.nls_map = NULL;
|
||||||
|
|
||||||
sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
|
sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
|
||||||
if (!sbi)
|
if (!sbi)
|
||||||
|
@ -2275,8 +2280,8 @@ error_out:
|
||||||
iput(sbi->s_vat_inode);
|
iput(sbi->s_vat_inode);
|
||||||
parse_options_failure:
|
parse_options_failure:
|
||||||
#ifdef CONFIG_UDF_NLS
|
#ifdef CONFIG_UDF_NLS
|
||||||
if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
|
if (uopt.nls_map)
|
||||||
unload_nls(sbi->s_nls_map);
|
unload_nls(uopt.nls_map);
|
||||||
#endif
|
#endif
|
||||||
if (lvid_open)
|
if (lvid_open)
|
||||||
udf_close_lvid(sb);
|
udf_close_lvid(sb);
|
||||||
|
|
Loading…
Reference in a new issue