diff options
author | Cyrill Gorcunov <gorcunov@gmail.com> | 2010-07-27 11:56:07 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2010-07-27 11:56:07 -0400 |
commit | dcc7dae3cb21184a317f10a12250bd8d6f458077 (patch) | |
tree | 1f40c22059a9ccbb0ef3ea6fde0e015290db2765 /fs/ext4/super.c | |
parent | 0c095c7f113e9fd05913d6e1b2cccbe356be039e (diff) |
ext4: Fix potential memory leak in ext4_fill_super
Under heavy memory pressure we may hit out of memory
situation and as result kstrdup'ed options will not be
freed. Fix it.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r-- | fs/ext4/super.c | 8 |
1 files changed, 5 insertions, 3 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index ed00c14d7081..d573f6c1a4de 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -2550,7 +2550,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
2550 | struct inode *root; | 2550 | struct inode *root; |
2551 | char *cp; | 2551 | char *cp; |
2552 | const char *descr; | 2552 | const char *descr; |
2553 | int ret = -EINVAL; | 2553 | int ret = -ENOMEM; |
2554 | int blocksize; | 2554 | int blocksize; |
2555 | unsigned int db_count; | 2555 | unsigned int db_count; |
2556 | unsigned int i; | 2556 | unsigned int i; |
@@ -2561,13 +2561,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
2561 | 2561 | ||
2562 | sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); | 2562 | sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); |
2563 | if (!sbi) | 2563 | if (!sbi) |
2564 | return -ENOMEM; | 2564 | goto out_free_orig; |
2565 | 2565 | ||
2566 | sbi->s_blockgroup_lock = | 2566 | sbi->s_blockgroup_lock = |
2567 | kzalloc(sizeof(struct blockgroup_lock), GFP_KERNEL); | 2567 | kzalloc(sizeof(struct blockgroup_lock), GFP_KERNEL); |
2568 | if (!sbi->s_blockgroup_lock) { | 2568 | if (!sbi->s_blockgroup_lock) { |
2569 | kfree(sbi); | 2569 | kfree(sbi); |
2570 | return -ENOMEM; | 2570 | goto out_free_orig; |
2571 | } | 2571 | } |
2572 | sb->s_fs_info = sbi; | 2572 | sb->s_fs_info = sbi; |
2573 | sbi->s_mount_opt = 0; | 2573 | sbi->s_mount_opt = 0; |
@@ -2584,6 +2584,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
2584 | for (cp = sb->s_id; (cp = strchr(cp, '/'));) | 2584 | for (cp = sb->s_id; (cp = strchr(cp, '/'));) |
2585 | *cp = '!'; | 2585 | *cp = '!'; |
2586 | 2586 | ||
2587 | ret = -EINVAL; | ||
2587 | blocksize = sb_min_blocksize(sb, EXT4_MIN_BLOCK_SIZE); | 2588 | blocksize = sb_min_blocksize(sb, EXT4_MIN_BLOCK_SIZE); |
2588 | if (!blocksize) { | 2589 | if (!blocksize) { |
2589 | ext4_msg(sb, KERN_ERR, "unable to set blocksize"); | 2590 | ext4_msg(sb, KERN_ERR, "unable to set blocksize"); |
@@ -3190,6 +3191,7 @@ out_fail: | |||
3190 | kfree(sbi->s_blockgroup_lock); | 3191 | kfree(sbi->s_blockgroup_lock); |
3191 | kfree(sbi); | 3192 | kfree(sbi); |
3192 | lock_kernel(); | 3193 | lock_kernel(); |
3194 | out_free_orig: | ||
3193 | kfree(orig_data); | 3195 | kfree(orig_data); |
3194 | return ret; | 3196 | return ret; |
3195 | } | 3197 | } |