Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ramfs: fix double freeing s_fs_info on failed mount

If ramfs mount fails, s_fs_info will be freed twice in ramfs_fill_super()
and ramfs_kill_sb(), leading to kernel oops.

Consolidate and beautify the code.
Make sure s_fs_info and s_root are in known good states.

Acked-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Ingo Molnar and committed by
Linus Torvalds
f8201abc 4ef4327b

+11 -8
+11 -8
fs/ramfs/inode.c
··· 221 221 save_mount_options(sb, data); 222 222 223 223 fsi = kzalloc(sizeof(struct ramfs_fs_info), GFP_KERNEL); 224 + sb->s_fs_info = fsi; 224 225 if (!fsi) { 225 226 err = -ENOMEM; 226 227 goto fail; 227 228 } 228 - sb->s_fs_info = fsi; 229 229 230 230 err = ramfs_parse_options(data, &fsi->mount_opts); 231 231 if (err) 232 232 goto fail; 233 233 234 - sb->s_maxbytes = MAX_LFS_FILESIZE; 235 - sb->s_blocksize = PAGE_CACHE_SIZE; 236 - sb->s_blocksize_bits = PAGE_CACHE_SHIFT; 237 - sb->s_magic = RAMFS_MAGIC; 238 - sb->s_op = &ramfs_ops; 239 - sb->s_time_gran = 1; 234 + sb->s_maxbytes = MAX_LFS_FILESIZE; 235 + sb->s_blocksize = PAGE_CACHE_SIZE; 236 + sb->s_blocksize_bits = PAGE_CACHE_SHIFT; 237 + sb->s_magic = RAMFS_MAGIC; 238 + sb->s_op = &ramfs_ops; 239 + sb->s_time_gran = 1; 240 + 240 241 inode = ramfs_get_inode(sb, S_IFDIR | fsi->mount_opts.mode, 0); 241 242 if (!inode) { 242 243 err = -ENOMEM; ··· 245 244 } 246 245 247 246 root = d_alloc_root(inode); 247 + sb->s_root = root; 248 248 if (!root) { 249 249 err = -ENOMEM; 250 250 goto fail; 251 251 } 252 - sb->s_root = root; 252 + 253 253 return 0; 254 254 fail: 255 255 kfree(fsi); 256 + sb->s_fs_info = NULL; 256 257 iput(inode); 257 258 return err; 258 259 }