diff options
author | Chengguang Xu <cgxu519@icloud.com> | 2018-02-25 21:25:07 +0800 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2018-03-02 14:23:12 +0100 |
commit | 785dffe1daf95c176504dea3069c9df11af7ff15 (patch) | |
tree | c2fcc45cbd2e09ee2c1e0a2adc83fc9d205f31fa /fs/udf | |
parent | d09099051057bbae5e1a887167ad6189ac8bfca4 (diff) | |
download | linux-785dffe1daf95c176504dea3069c9df11af7ff15.tar.gz linux-785dffe1daf95c176504dea3069c9df11af7ff15.tar.bz2 linux-785dffe1daf95c176504dea3069c9df11af7ff15.zip |
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>
Diffstat (limited to 'fs/udf')
-rw-r--r-- | fs/udf/super.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/fs/udf/super.c b/fs/udf/super.c index bf5f6084dcb2..7949c338efa5 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -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; @@ -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: @@ -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; @@ -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) @@ -2275,8 +2280,8 @@ error_out: 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); |