Blame SOURCES/0096-fs-ntfs3-Fix-memory-leak-if-fill_super-failed.patch

Kmods SIG 8b815c
From 9b75450d6c580100611743fa7e690ea3cb47cd4a Mon Sep 17 00:00:00 2001
Kmods SIG 8b815c
From: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
Kmods SIG 8b815c
Date: Tue, 28 Sep 2021 19:00:30 +0300
Kmods SIG 8b815c
Subject: [Backport 9b75450d6c58] src: Fix memory leak if fill_super
Kmods SIG 8b815c
 failed
Kmods SIG 8b815c
Kmods SIG 8b815c
In ntfs_init_fs_context we allocate memory in fc->s_fs_info.
Kmods SIG 8b815c
In case of failed mount we must free it in ntfs_fill_super.
Kmods SIG 8b815c
We can't do it in ntfs_fs_free, because ntfs_fs_free called
Kmods SIG 8b815c
with fc->s_fs_info == NULL.
Kmods SIG 8b815c
fc->s_fs_info became NULL in sget_fc.
Kmods SIG 8b815c
Kmods SIG 8b815c
Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
Kmods SIG 8b815c
---
Kmods SIG 8b815c
 src/super.c | 90 ++++++++++++++++++++++++++++++------------------
Kmods SIG 8b815c
 1 file changed, 56 insertions(+), 34 deletions(-)
Kmods SIG 8b815c
Kmods SIG 8b815c
diff --git a/src/super.c b/src/super.c
Kmods SIG 8b815c
index 705d8b4f4894fbcc63f018e41437a54d6a0e1e6f..d41d76979e121fd9e836ef0072b122ab6de3735b 100644
Kmods SIG 8b815c
--- a/src/super.c
Kmods SIG 8b815c
+++ b/src/super.c
Kmods SIG 8b815c
@@ -908,7 +908,8 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
Kmods SIG 8b815c
 	if (IS_ERR(sbi->options->nls)) {
Kmods SIG 8b815c
 		sbi->options->nls = NULL;
Kmods SIG 8b815c
 		errorf(fc, "Cannot load nls %s", sbi->options->nls_name);
Kmods SIG 8b815c
-		return -EINVAL;
Kmods SIG 8b815c
+		err = -EINVAL;
Kmods SIG 8b815c
+		goto out;
Kmods SIG 8b815c
 	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	rq = bdev_get_queue(bdev);
Kmods SIG 8b815c
@@ -922,7 +923,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
Kmods SIG 8b815c
 	err = ntfs_init_from_boot(sb, rq ? queue_logical_block_size(rq) : 512,
Kmods SIG 8b815c
 				  bdev->bd_inode->i_size);
Kmods SIG 8b815c
 	if (err)
Kmods SIG 8b815c
-		return err;
Kmods SIG 8b815c
+		goto out;
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	/*
Kmods SIG 8b815c
 	 * Load $Volume. This should be done before $LogFile
Kmods SIG 8b815c
@@ -933,7 +934,8 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
Kmods SIG 8b815c
 	inode = ntfs_iget5(sb, &ref, &NAME_VOLUME);
Kmods SIG 8b815c
 	if (IS_ERR(inode)) {
Kmods SIG 8b815c
 		ntfs_err(sb, "Failed to load $Volume.");
Kmods SIG 8b815c
-		return PTR_ERR(inode);
Kmods SIG 8b815c
+		err = PTR_ERR(inode);
Kmods SIG 8b815c
+		goto out;
Kmods SIG 8b815c
 	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	ni = ntfs_i(inode);
Kmods SIG 8b815c
@@ -954,19 +956,19 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
Kmods SIG 8b815c
 	} else {
Kmods SIG 8b815c
 		/* Should we break mounting here? */
Kmods SIG 8b815c
 		//err = -EINVAL;
Kmods SIG 8b815c
-		//goto out;
Kmods SIG 8b815c
+		//goto put_inode_out;
Kmods SIG 8b815c
 	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	attr = ni_find_attr(ni, attr, NULL, ATTR_VOL_INFO, NULL, 0, NULL, NULL);
Kmods SIG 8b815c
 	if (!attr || is_attr_ext(attr)) {
Kmods SIG 8b815c
 		err = -EINVAL;
Kmods SIG 8b815c
-		goto out;
Kmods SIG 8b815c
+		goto put_inode_out;
Kmods SIG 8b815c
 	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	info = resident_data_ex(attr, SIZEOF_ATTRIBUTE_VOLUME_INFO);
Kmods SIG 8b815c
 	if (!info) {
Kmods SIG 8b815c
 		err = -EINVAL;
Kmods SIG 8b815c
-		goto out;
Kmods SIG 8b815c
+		goto put_inode_out;
Kmods SIG 8b815c
 	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	sbi->volume.major_ver = info->major_ver;
Kmods SIG 8b815c
@@ -980,7 +982,8 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
Kmods SIG 8b815c
 	inode = ntfs_iget5(sb, &ref, &NAME_MIRROR);
Kmods SIG 8b815c
 	if (IS_ERR(inode)) {
Kmods SIG 8b815c
 		ntfs_err(sb, "Failed to load $MFTMirr.");
Kmods SIG 8b815c
-		return PTR_ERR(inode);
Kmods SIG 8b815c
+		err = PTR_ERR(inode);
Kmods SIG 8b815c
+		goto out;
Kmods SIG 8b815c
 	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	sbi->mft.recs_mirr =
Kmods SIG 8b815c
@@ -994,14 +997,15 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
Kmods SIG 8b815c
 	inode = ntfs_iget5(sb, &ref, &NAME_LOGFILE);
Kmods SIG 8b815c
 	if (IS_ERR(inode)) {
Kmods SIG 8b815c
 		ntfs_err(sb, "Failed to load \x24LogFile.");
Kmods SIG 8b815c
-		return PTR_ERR(inode);
Kmods SIG 8b815c
+		err = PTR_ERR(inode);
Kmods SIG 8b815c
+		goto out;
Kmods SIG 8b815c
 	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	ni = ntfs_i(inode);
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	err = ntfs_loadlog_and_replay(ni, sbi);
Kmods SIG 8b815c
 	if (err)
Kmods SIG 8b815c
-		goto out;
Kmods SIG 8b815c
+		goto put_inode_out;
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	iput(inode);
Kmods SIG 8b815c
 
Kmods SIG 8b815c
@@ -1009,14 +1013,16 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
Kmods SIG 8b815c
 		if (!sb_rdonly(sb)) {
Kmods SIG 8b815c
 			ntfs_warn(sb,
Kmods SIG 8b815c
 				  "failed to replay log file. Can't mount rw!");
Kmods SIG 8b815c
-			return -EINVAL;
Kmods SIG 8b815c
+			err = -EINVAL;
Kmods SIG 8b815c
+			goto out;
Kmods SIG 8b815c
 		}
Kmods SIG 8b815c
 	} else if (sbi->volume.flags & VOLUME_FLAG_DIRTY) {
Kmods SIG 8b815c
 		if (!sb_rdonly(sb) && !sbi->options->force) {
Kmods SIG 8b815c
 			ntfs_warn(
Kmods SIG 8b815c
 				sb,
Kmods SIG 8b815c
 				"volume is dirty and \"force\" flag is not set!");
Kmods SIG 8b815c
-			return -EINVAL;
Kmods SIG 8b815c
+			err = -EINVAL;
Kmods SIG 8b815c
+			goto out;
Kmods SIG 8b815c
 		}
Kmods SIG 8b815c
 	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
@@ -1027,7 +1033,8 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
Kmods SIG 8b815c
 	inode = ntfs_iget5(sb, &ref, &NAME_MFT);
Kmods SIG 8b815c
 	if (IS_ERR(inode)) {
Kmods SIG 8b815c
 		ntfs_err(sb, "Failed to load $MFT.");
Kmods SIG 8b815c
-		return PTR_ERR(inode);
Kmods SIG 8b815c
+		err = PTR_ERR(inode);
Kmods SIG 8b815c
+		goto out;
Kmods SIG 8b815c
 	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	ni = ntfs_i(inode);
Kmods SIG 8b815c
@@ -1038,11 +1045,11 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	err = wnd_init(&sbi->mft.bitmap, sb, tt);
Kmods SIG 8b815c
 	if (err)
Kmods SIG 8b815c
-		goto out;
Kmods SIG 8b815c
+		goto put_inode_out;
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	err = ni_load_all_mi(ni);
Kmods SIG 8b815c
 	if (err)
Kmods SIG 8b815c
-		goto out;
Kmods SIG 8b815c
+		goto put_inode_out;
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	sbi->mft.ni = ni;
Kmods SIG 8b815c
 
Kmods SIG 8b815c
@@ -1052,7 +1059,8 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
Kmods SIG 8b815c
 	inode = ntfs_iget5(sb, &ref, &NAME_BADCLUS);
Kmods SIG 8b815c
 	if (IS_ERR(inode)) {
Kmods SIG 8b815c
 		ntfs_err(sb, "Failed to load $BadClus.");
Kmods SIG 8b815c
-		return PTR_ERR(inode);
Kmods SIG 8b815c
+		err = PTR_ERR(inode);
Kmods SIG 8b815c
+		goto out;
Kmods SIG 8b815c
 	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	ni = ntfs_i(inode);
Kmods SIG 8b815c
@@ -1075,13 +1083,14 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
Kmods SIG 8b815c
 	inode = ntfs_iget5(sb, &ref, &NAME_BITMAP);
Kmods SIG 8b815c
 	if (IS_ERR(inode)) {
Kmods SIG 8b815c
 		ntfs_err(sb, "Failed to load $Bitmap.");
Kmods SIG 8b815c
-		return PTR_ERR(inode);
Kmods SIG 8b815c
+		err = PTR_ERR(inode);
Kmods SIG 8b815c
+		goto out;
Kmods SIG 8b815c
 	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 #ifndef CONFIG_NTFS3_64BIT_CLUSTER
Kmods SIG 8b815c
 	if (inode->i_size >> 32) {
Kmods SIG 8b815c
 		err = -EINVAL;
Kmods SIG 8b815c
-		goto out;
Kmods SIG 8b815c
+		goto put_inode_out;
Kmods SIG 8b815c
 	}
Kmods SIG 8b815c
 #endif
Kmods SIG 8b815c
 
Kmods SIG 8b815c
@@ -1089,21 +1098,21 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
Kmods SIG 8b815c
 	tt = sbi->used.bitmap.nbits;
Kmods SIG 8b815c
 	if (inode->i_size < bitmap_size(tt)) {
Kmods SIG 8b815c
 		err = -EINVAL;
Kmods SIG 8b815c
-		goto out;
Kmods SIG 8b815c
+		goto put_inode_out;
Kmods SIG 8b815c
 	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	/* Not necessary. */
Kmods SIG 8b815c
 	sbi->used.bitmap.set_tail = true;
Kmods SIG 8b815c
 	err = wnd_init(&sbi->used.bitmap, sb, tt);
Kmods SIG 8b815c
 	if (err)
Kmods SIG 8b815c
-		goto out;
Kmods SIG 8b815c
+		goto put_inode_out;
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	iput(inode);
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	/* Compute the MFT zone. */
Kmods SIG 8b815c
 	err = ntfs_refresh_zone(sbi);
Kmods SIG 8b815c
 	if (err)
Kmods SIG 8b815c
-		return err;
Kmods SIG 8b815c
+		goto out;
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	/* Load $AttrDef. */
Kmods SIG 8b815c
 	ref.low = cpu_to_le32(MFT_REC_ATTR);
Kmods SIG 8b815c
@@ -1111,18 +1120,19 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
Kmods SIG 8b815c
 	inode = ntfs_iget5(sb, &ref, &NAME_ATTRDEF);
Kmods SIG 8b815c
 	if (IS_ERR(inode)) {
Kmods SIG 8b815c
 		ntfs_err(sb, "Failed to load $AttrDef -> %d", err);
Kmods SIG 8b815c
-		return PTR_ERR(inode);
Kmods SIG 8b815c
+		err = PTR_ERR(inode);
Kmods SIG 8b815c
+		goto out;
Kmods SIG 8b815c
 	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	if (inode->i_size < sizeof(struct ATTR_DEF_ENTRY)) {
Kmods SIG 8b815c
 		err = -EINVAL;
Kmods SIG 8b815c
-		goto out;
Kmods SIG 8b815c
+		goto put_inode_out;
Kmods SIG 8b815c
 	}
Kmods SIG 8b815c
 	bytes = inode->i_size;
Kmods SIG 8b815c
 	sbi->def_table = t = kmalloc(bytes, GFP_NOFS);
Kmods SIG 8b815c
 	if (!t) {
Kmods SIG 8b815c
 		err = -ENOMEM;
Kmods SIG 8b815c
-		goto out;
Kmods SIG 8b815c
+		goto put_inode_out;
Kmods SIG 8b815c
 	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	for (done = idx = 0; done < bytes; done += PAGE_SIZE, idx++) {
Kmods SIG 8b815c
@@ -1131,7 +1141,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 		if (IS_ERR(page)) {
Kmods SIG 8b815c
 			err = PTR_ERR(page);
Kmods SIG 8b815c
-			goto out;
Kmods SIG 8b815c
+			goto put_inode_out;
Kmods SIG 8b815c
 		}
Kmods SIG 8b815c
 		memcpy(Add2Ptr(t, done), page_address(page),
Kmods SIG 8b815c
 		       min(PAGE_SIZE, tail));
Kmods SIG 8b815c
@@ -1139,7 +1149,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 		if (!idx && ATTR_STD != t->type) {
Kmods SIG 8b815c
 			err = -EINVAL;
Kmods SIG 8b815c
-			goto out;
Kmods SIG 8b815c
+			goto put_inode_out;
Kmods SIG 8b815c
 		}
Kmods SIG 8b815c
 	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
@@ -1173,12 +1183,13 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
Kmods SIG 8b815c
 	inode = ntfs_iget5(sb, &ref, &NAME_UPCASE);
Kmods SIG 8b815c
 	if (IS_ERR(inode)) {
Kmods SIG 8b815c
 		ntfs_err(sb, "Failed to load $UpCase.");
Kmods SIG 8b815c
-		return PTR_ERR(inode);
Kmods SIG 8b815c
+		err = PTR_ERR(inode);
Kmods SIG 8b815c
+		goto out;
Kmods SIG 8b815c
 	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	if (inode->i_size != 0x10000 * sizeof(short)) {
Kmods SIG 8b815c
 		err = -EINVAL;
Kmods SIG 8b815c
-		goto out;
Kmods SIG 8b815c
+		goto put_inode_out;
Kmods SIG 8b815c
 	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	for (idx = 0; idx < (0x10000 * sizeof(short) >> PAGE_SHIFT); idx++) {
Kmods SIG 8b815c
@@ -1188,7 +1199,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 		if (IS_ERR(page)) {
Kmods SIG 8b815c
 			err = PTR_ERR(page);
Kmods SIG 8b815c
-			goto out;
Kmods SIG 8b815c
+			goto put_inode_out;
Kmods SIG 8b815c
 		}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 		src = page_address(page);
Kmods SIG 8b815c
@@ -1214,7 +1225,7 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
Kmods SIG 8b815c
 		/* Load $Secure. */
Kmods SIG 8b815c
 		err = ntfs_security_init(sbi);
Kmods SIG 8b815c
 		if (err)
Kmods SIG 8b815c
-			return err;
Kmods SIG 8b815c
+			goto out;
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 		/* Load $Extend. */
Kmods SIG 8b815c
 		err = ntfs_extend_init(sbi);
Kmods SIG 8b815c
@@ -1239,19 +1250,30 @@ static int ntfs_fill_super(struct super_block *sb, struct fs_context *fc)
Kmods SIG 8b815c
 	inode = ntfs_iget5(sb, &ref, &NAME_ROOT);
Kmods SIG 8b815c
 	if (IS_ERR(inode)) {
Kmods SIG 8b815c
 		ntfs_err(sb, "Failed to load root.");
Kmods SIG 8b815c
-		return PTR_ERR(inode);
Kmods SIG 8b815c
+		err = PTR_ERR(inode);
Kmods SIG 8b815c
+		goto out;
Kmods SIG 8b815c
 	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	sb->s_root = d_make_root(inode);
Kmods SIG 8b815c
-	if (!sb->s_root)
Kmods SIG 8b815c
-		return -ENOMEM;
Kmods SIG 8b815c
+	if (!sb->s_root) {
Kmods SIG 8b815c
+		err = -ENOMEM;
Kmods SIG 8b815c
+		goto put_inode_out;
Kmods SIG 8b815c
+	}
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	fc->fs_private = NULL;
Kmods SIG 8b815c
-	fc->s_fs_info = NULL;
Kmods SIG 8b815c
 
Kmods SIG 8b815c
 	return 0;
Kmods SIG 8b815c
-out:
Kmods SIG 8b815c
+
Kmods SIG 8b815c
+put_inode_out:
Kmods SIG 8b815c
 	iput(inode);
Kmods SIG 8b815c
+out:
Kmods SIG 8b815c
+	/*
Kmods SIG 8b815c
+	 * Free resources here.
Kmods SIG 8b815c
+	 * ntfs_fs_free will be called with fc->s_fs_info = NULL
Kmods SIG 8b815c
+	 */
Kmods SIG 8b815c
+	put_ntfs(sbi);
Kmods SIG 8b815c
+	sb->s_fs_info = NULL;
Kmods SIG 8b815c
+
Kmods SIG 8b815c
 	return err;
Kmods SIG 8b815c
 }
Kmods SIG 8b815c
 
Kmods SIG 8b815c
-- 
Kmods SIG 8b815c
2.31.1
Kmods SIG 8b815c