lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <4fafc9c42962e1fdc8ce44b21fa977df5de0679e.1742800203.git.ojaswin@linux.ibm.com>
Date: Mon, 24 Mar 2025 13:07:09 +0530
From: Ojaswin Mujoo <ojaswin@...ux.ibm.com>
To: linux-ext4@...r.kernel.org, "Theodore Ts'o" <tytso@....edu>
Cc: John Garry <john.g.garry@...cle.com>, dchinner@...hat.com,
        "Darrick J . Wong" <djwong@...nel.org>,
        Ritesh Harjani <ritesh.list@...il.com>, linux-kernel@...r.kernel.org
Subject: [RFC v3 11/11] ext4: disallow unaligned deallocations on forcealign inodes

When forcealign is set, an unaligned deallocation can disturb the
alignment of the mappings of the file by introducing unaligned holes/unwritten
extents to it. This could then lead to increased allocations failures on the
file in future.

To avoid this, disallow deallocations or extent shifting operations (like insert
range) unless they are aligned to extsize as well.

Note that this is a relatively strict approach which can be relaxed a bit more
in the future by using partial zeroing tricks etc.

Signed-off-by: Ojaswin Mujoo <ojaswin@...ux.ibm.com>
---
 fs/ext4/extents.c | 36 ++++++++++++++++++++++++++++++++++++
 fs/ext4/inode.c   | 12 ++++++++++++
 2 files changed, 48 insertions(+)

diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 1835e18f0eef..1ac5bb8cbbde 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4754,6 +4754,18 @@ static long ext4_zero_range(struct file *file, loff_t offset,
 			return ret;
 	}
 
+	if (ext4_should_use_forcealign(inode)) {
+		u32 extsize_bytes = ext4_inode_get_extsize(EXT4_I(inode))
+				    << inode->i_blkbits;
+
+		if (!IS_ALIGNED(offset | end, extsize_bytes)) {
+			ext4_warning(
+				inode->i_sb,
+				"tried unaligned operation on forcealign inode");
+			return -EINVAL;
+		}
+	}
+
 	flags = EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT;
 	/* Preallocate the range including the unaligned edges */
 	if (!IS_ALIGNED(offset | end, blocksize)) {
@@ -5473,6 +5485,18 @@ static int ext4_collapse_range(struct file *file, loff_t offset, loff_t len)
 	if (end >= inode->i_size)
 		return -EINVAL;
 
+	if (ext4_should_use_forcealign(inode)) {
+		u32 extsize_bytes = ext4_inode_get_extsize(EXT4_I(inode))
+				    << inode->i_blkbits;
+
+		if (!IS_ALIGNED(offset | end, extsize_bytes)) {
+			ext4_warning(
+				inode->i_sb,
+				"tried unaligned operation on forcealign inode");
+			return -EINVAL;
+		}
+	}
+
 	/*
 	 * Write tail of the last page before removed range and data that
 	 * will be shifted since they will get removed from the page cache
@@ -5573,6 +5597,18 @@ static int ext4_insert_range(struct file *file, loff_t offset, loff_t len)
 	if (len > inode->i_sb->s_maxbytes - inode->i_size)
 		return -EFBIG;
 
+	if (ext4_should_use_forcealign(inode)) {
+		u32 extsize_bytes = ext4_inode_get_extsize(EXT4_I(inode))
+				    << inode->i_blkbits;
+
+		if (!IS_ALIGNED(offset | (offset + len), extsize_bytes)) {
+			ext4_warning(
+				sb,
+				"tried unaligned operation on forcealign inode");
+			return -EINVAL;
+		}
+	}
+
 	/*
 	 * Write out all dirty pages. Need to round down to align start offset
 	 * to page size boundary for page size > block size.
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 5b36e62872d6..4c974e461061 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -4397,6 +4397,18 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length)
 		end = max_end;
 	length = end - offset;
 
+	if (ext4_should_use_forcealign(inode)) {
+		u32 extsize_bytes = ext4_inode_get_extsize(EXT4_I(inode))
+				    << inode->i_blkbits;
+
+		if (!IS_ALIGNED(offset | end, extsize_bytes)) {
+			ext4_warning(
+				sb,
+				"tried unaligned operation on forcealign inode");
+			return -EINVAL;
+		}
+	}
+
 	/*
 	 * Attach jinode to inode for jbd2 if we do any zeroing of partial
 	 * block.
-- 
2.48.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ