[PATCH] fs: fix s_fs_info leak when setup_bdev_super() fails
hanzhijian <[email protected]>
| Newsgroups | org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
get_tree_bdev_flags() hands fc->s_fs_info to the newly allocated super block in sget_fc() and clears fc->s_fs_info. If setup_bdev_super() then fails (the block device cannot be opened, is read-only, or is frozen), fill_super() is never called and sb->s_root stays NULL. The cleanup path calls deactivate_locked_super(), whose generic_shutdown_super() skips the whole sb->s_root block -- including the put_super() callback that would otherwise release s_fs_info -- leaking the allocation made by the filesystem's init_fs_context(). Hand s_fs_info back to the fs_context when setup_bdev_super() fails so that put_fs_context() releases it through the filesystem's free() callback. Reported-by: [email protected] Link: https://syzkaller.appspot.com/bug?extid=1c70732df5fd4f0e4fbb Signed-off-by: hanzhijian <[email protected]> --- fs/super.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/fs/super.c b/fs/super.c index 05e443173..8b978b67b 100644 --- a/fs/super.c +++ b/fs/super.c @@ -1883,8 +1883,19 @@ int get_tree_bdev_flags(struct fs_context *fc, } } else { error = setup_bdev_super(s, fc->sb_flags, fc); - if (!error) - error = fill_super(s, fc); + if (error) { + /* + * fill_super() was not called, so nothing has taken + * ownership of fc->s_fs_info. Hand it back so that + * put_fs_context() can release it, otherwise it + * leaks. + */ + fc->s_fs_info = s->s_fs_info; + s->s_fs_info = NULL; + deactivate_locked_super(s); + return error; + } + error = fill_super(s, fc); if (error) { deactivate_locked_super(s); return error; -- 2.43.0