diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2010-03-20 22:32:26 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2010-05-21 18:31:13 -0400 |
commit | decabd6650915a9534dad09e967115513be12b24 (patch) | |
tree | 3e4aa8ed78535f3a34b60e363e7b13efbd7ea62c | |
parent | 894680710d813137077ad7cb351b713f64cabbdf (diff) |
fix a couple of ecryptfs leaks
First of all, get_sb_nodev() grabs anon dev minor and we
never free it in ecryptfs ->kill_sb(). Moreover, on one
of the failure exits in ecryptfs_get_sb() we leak things -
it happens before we set ->s_root and ->put_super() won't
be called in that case. Solution: kill ->put_super(), do
all that stuff in ->kill_sb(). And use kill_anon_sb() instead
of generic_shutdown_super() to deal with anon dev leak.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/ecryptfs/main.c | 9 | ||||
-rw-r--r-- | fs/ecryptfs/super.c | 22 |
2 files changed, 7 insertions, 24 deletions
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 760983d0f25e..36268db29ea1 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c | |||
@@ -633,11 +633,16 @@ out: | |||
633 | * @sb: The ecryptfs super block | 633 | * @sb: The ecryptfs super block |
634 | * | 634 | * |
635 | * Used to bring the superblock down and free the private data. | 635 | * Used to bring the superblock down and free the private data. |
636 | * Private data is free'd in ecryptfs_put_super() | ||
637 | */ | 636 | */ |
638 | static void ecryptfs_kill_block_super(struct super_block *sb) | 637 | static void ecryptfs_kill_block_super(struct super_block *sb) |
639 | { | 638 | { |
640 | generic_shutdown_super(sb); | 639 | struct ecryptfs_sb_info *sb_info = ecryptfs_superblock_to_private(sb); |
640 | kill_anon_super(sb); | ||
641 | if (!sb_info) | ||
642 | return; | ||
643 | ecryptfs_destroy_mount_crypt_stat(&sb_info->mount_crypt_stat); | ||
644 | bdi_destroy(&sb_info->bdi); | ||
645 | kmem_cache_free(ecryptfs_sb_info_cache, sb_info); | ||
641 | } | 646 | } |
642 | 647 | ||
643 | static struct file_system_type ecryptfs_fs_type = { | 648 | static struct file_system_type ecryptfs_fs_type = { |
diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c index 0c0ae491d231..0435886e4a9f 100644 --- a/fs/ecryptfs/super.c +++ b/fs/ecryptfs/super.c | |||
@@ -109,27 +109,6 @@ void ecryptfs_init_inode(struct inode *inode, struct inode *lower_inode) | |||
109 | } | 109 | } |
110 | 110 | ||
111 | /** | 111 | /** |
112 | * ecryptfs_put_super | ||
113 | * @sb: Pointer to the ecryptfs super block | ||
114 | * | ||
115 | * Final actions when unmounting a file system. | ||
116 | * This will handle deallocation and release of our private data. | ||
117 | */ | ||
118 | static void ecryptfs_put_super(struct super_block *sb) | ||
119 | { | ||
120 | struct ecryptfs_sb_info *sb_info = ecryptfs_superblock_to_private(sb); | ||
121 | |||
122 | lock_kernel(); | ||
123 | |||
124 | ecryptfs_destroy_mount_crypt_stat(&sb_info->mount_crypt_stat); | ||
125 | bdi_destroy(&sb_info->bdi); | ||
126 | kmem_cache_free(ecryptfs_sb_info_cache, sb_info); | ||
127 | ecryptfs_set_superblock_private(sb, NULL); | ||
128 | |||
129 | unlock_kernel(); | ||
130 | } | ||
131 | |||
132 | /** | ||
133 | * ecryptfs_statfs | 112 | * ecryptfs_statfs |
134 | * @sb: The ecryptfs super block | 113 | * @sb: The ecryptfs super block |
135 | * @buf: The struct kstatfs to fill in with stats | 114 | * @buf: The struct kstatfs to fill in with stats |
@@ -203,7 +182,6 @@ const struct super_operations ecryptfs_sops = { | |||
203 | .alloc_inode = ecryptfs_alloc_inode, | 182 | .alloc_inode = ecryptfs_alloc_inode, |
204 | .destroy_inode = ecryptfs_destroy_inode, | 183 | .destroy_inode = ecryptfs_destroy_inode, |
205 | .drop_inode = generic_delete_inode, | 184 | .drop_inode = generic_delete_inode, |
206 | .put_super = ecryptfs_put_super, | ||
207 | .statfs = ecryptfs_statfs, | 185 | .statfs = ecryptfs_statfs, |
208 | .remount_fs = NULL, | 186 | .remount_fs = NULL, |
209 | .clear_inode = ecryptfs_clear_inode, | 187 | .clear_inode = ecryptfs_clear_inode, |