[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.