aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext3
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2012-12-31 06:38:36 -0500
committerJan Kara <jack@suse.cz>2013-01-21 05:19:55 -0500
commitf56426ae4d4414c9c996567710dceecbdfc39acc (patch)
tree1ef907778df97d0ac0c0a680d5a44280324ad1cb /fs/ext3
parent306a74920ba9ccf6b5f110f97c1cb6bb2caeff93 (diff)
ext3: Fix memory leak when quota options are specified multiple times
When usrjquota or grpjquota mount options are specified several times, we leak memory storing the names. Free the memory correctly. Reported-by: Chen Gang <gang.chen@asianux.com> Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/ext3')
-rw-r--r--fs/ext3/super.c51
1 files changed, 30 insertions, 21 deletions
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 6e50223b3299..0926fe46ae3e 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -916,21 +916,24 @@ static int set_qf_name(struct super_block *sb, int qtype, substring_t *args)
916 "Not enough memory for storing quotafile name"); 916 "Not enough memory for storing quotafile name");
917 return 0; 917 return 0;
918 } 918 }
919 if (sbi->s_qf_names[qtype] && 919 if (sbi->s_qf_names[qtype]) {
920 strcmp(sbi->s_qf_names[qtype], qname)) { 920 int same = !strcmp(sbi->s_qf_names[qtype], qname);
921 ext3_msg(sb, KERN_ERR, 921
922 "%s quota file already specified", QTYPE2NAME(qtype));
923 kfree(qname); 922 kfree(qname);
924 return 0; 923 if (!same) {
924 ext3_msg(sb, KERN_ERR,
925 "%s quota file already specified",
926 QTYPE2NAME(qtype));
927 }
928 return same;
925 } 929 }
926 sbi->s_qf_names[qtype] = qname; 930 if (strchr(qname, '/')) {
927 if (strchr(sbi->s_qf_names[qtype], '/')) {
928 ext3_msg(sb, KERN_ERR, 931 ext3_msg(sb, KERN_ERR,
929 "quotafile must be on filesystem root"); 932 "quotafile must be on filesystem root");
930 kfree(sbi->s_qf_names[qtype]); 933 kfree(qname);
931 sbi->s_qf_names[qtype] = NULL;
932 return 0; 934 return 0;
933 } 935 }
936 sbi->s_qf_names[qtype] = qname;
934 set_opt(sbi->s_mount_opt, QUOTA); 937 set_opt(sbi->s_mount_opt, QUOTA);
935 return 1; 938 return 1;
936} 939}
@@ -945,11 +948,10 @@ static int clear_qf_name(struct super_block *sb, int qtype) {
945 " when quota turned on"); 948 " when quota turned on");
946 return 0; 949 return 0;
947 } 950 }
948 /* 951 if (sbi->s_qf_names[qtype]) {
949 * The space will be released later when all options are confirmed 952 kfree(sbi->s_qf_names[qtype]);
950 * to be correct 953 sbi->s_qf_names[qtype] = NULL;
951 */ 954 }
952 sbi->s_qf_names[qtype] = NULL;
953 return 1; 955 return 1;
954} 956}
955#endif 957#endif
@@ -2605,7 +2607,18 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
2605#ifdef CONFIG_QUOTA 2607#ifdef CONFIG_QUOTA
2606 old_opts.s_jquota_fmt = sbi->s_jquota_fmt; 2608 old_opts.s_jquota_fmt = sbi->s_jquota_fmt;
2607 for (i = 0; i < MAXQUOTAS; i++) 2609 for (i = 0; i < MAXQUOTAS; i++)
2608 old_opts.s_qf_names[i] = sbi->s_qf_names[i]; 2610 if (sbi->s_qf_names[i]) {
2611 old_opts.s_qf_names[i] = kstrdup(sbi->s_qf_names[i],
2612 GFP_KERNEL);
2613 if (!old_opts.s_qf_names[i]) {
2614 int j;
2615
2616 for (j = 0; j < i; j++)
2617 kfree(old_opts.s_qf_names[j]);
2618 return -ENOMEM;
2619 }
2620 } else
2621 old_opts.s_qf_names[i] = NULL;
2609#endif 2622#endif
2610 2623
2611 /* 2624 /*
@@ -2698,9 +2711,7 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
2698#ifdef CONFIG_QUOTA 2711#ifdef CONFIG_QUOTA
2699 /* Release old quota file names */ 2712 /* Release old quota file names */
2700 for (i = 0; i < MAXQUOTAS; i++) 2713 for (i = 0; i < MAXQUOTAS; i++)
2701 if (old_opts.s_qf_names[i] && 2714 kfree(old_opts.s_qf_names[i]);
2702 old_opts.s_qf_names[i] != sbi->s_qf_names[i])
2703 kfree(old_opts.s_qf_names[i]);
2704#endif 2715#endif
2705 if (enable_quota) 2716 if (enable_quota)
2706 dquot_resume(sb, -1); 2717 dquot_resume(sb, -1);
@@ -2714,9 +2725,7 @@ restore_opts:
2714#ifdef CONFIG_QUOTA 2725#ifdef CONFIG_QUOTA
2715 sbi->s_jquota_fmt = old_opts.s_jquota_fmt; 2726 sbi->s_jquota_fmt = old_opts.s_jquota_fmt;
2716 for (i = 0; i < MAXQUOTAS; i++) { 2727 for (i = 0; i < MAXQUOTAS; i++) {
2717 if (sbi->s_qf_names[i] && 2728 kfree(sbi->s_qf_names[i]);
2718 old_opts.s_qf_names[i] != sbi->s_qf_names[i])
2719 kfree(sbi->s_qf_names[i]);
2720 sbi->s_qf_names[i] = old_opts.s_qf_names[i]; 2729 sbi->s_qf_names[i] = old_opts.s_qf_names[i];
2721 } 2730 }
2722#endif 2731#endif