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 for Android: free password hash cracker in your pocket
[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20250803212031.3547641-20-sashal@kernel.org>
Date: Sun,  3 Aug 2025 17:20:27 -0400
From: Sasha Levin <sashal@...nel.org>
To: patches@...ts.linux.dev,
	stable@...r.kernel.org
Cc: Wei Gao <wegao@...e.com>,
	Jan Kara <jack@...e.cz>,
	Sasha Levin <sashal@...nel.org>,
	jack@...e.com,
	linux-ext4@...r.kernel.org
Subject: [PATCH AUTOSEL 6.6 20/23] ext2: Handle fiemap on empty files to prevent EINVAL

From: Wei Gao <wegao@...e.com>

[ Upstream commit a099b09a3342a0b28ea330e405501b5b4d0424b4 ]

Previously, ext2_fiemap would unconditionally apply "len = min_t(u64, len,
i_size_read(inode));", When inode->i_size was 0 (for an empty file), this
would reduce the requested len to 0. Passing len = 0 to iomap_fiemap could
then result in an -EINVAL error, even for valid queries on empty files.

Link: https://github.com/linux-test-project/ltp/issues/1246
Signed-off-by: Wei Gao <wegao@...e.com>
Signed-off-by: Jan Kara <jack@...e.cz>
Link: https://patch.msgid.link/20250613152402.3432135-1-wegao@suse.com
Signed-off-by: Sasha Levin <sashal@...nel.org>
---

LLM Generated explanations, may be completely bogus:

Based on my analysis of the commit and its context:

**Backport Status: YES**

This commit should be backported to stable kernel trees. Here's the
extensive analysis:

**1. Bug Fix Analysis:**
The commit fixes a user-visible bug where `fiemap` operations on empty
files (i_size = 0) could fail with -EINVAL. Looking at the code change
in fs/ext2/inode.c:

- **Before the fix**: `len = min_t(u64, len, i_size_read(inode));` would
  set len to 0 for empty files
- **After the fix**: The code adds a special check:
  ```c
  if (i_size == 0)
  i_size = 1;
  len = min_t(u64, len, i_size);
  ```

This ensures that even for empty files, we pass a non-zero length to
`iomap_fiemap()`.

**2. Root Cause:**
>From examining fs/ioctl.c:175-176, I found that `fiemap_prep()`
explicitly returns -EINVAL when len is 0:
```c
if (*len == 0)
    return -EINVAL;
```

This means `iomap_fiemap()` would fail when passed a zero length, which
is exactly what was happening for empty ext2 files.

**3. Impact Assessment:**
- **User-visible impact**: Applications using fiemap on empty ext2 files
  would receive unexpected EINVAL errors
- **Test failure**: The commit references an LTP (Linux Test Project)
  issue (#1246), indicating this breaks existing tests
- **Functional impact**: fiemap is a commonly used interface for
  discovering file extent mappings, and it should work on empty files
  (they simply have no extents)

**4. Fix Quality:**
- **Minimal and contained**: The fix adds only 10 lines of code with a
  clear comment explaining the rationale
- **Safe approach**: Setting i_size to 1 for the length calculation is
  safe because:
  - It only affects the length passed to iomap_fiemap
  - The comment explains this is specifically to avoid EINVAL from
    iomap_fiemap
  - The actual file size remains unchanged
- **No architectural changes**: This is a simple boundary condition fix

**5. Regression Risk:**
- **Low risk**: The change only affects the fiemap path for empty files
- **Well-tested path**: fiemap is a read-only operation
- **Clear boundary**: Only affects files where i_size == 0

**6. Stable Tree Criteria:**
This fix meets all the stable tree criteria:
- Fixes a real bug that users/tests hit
- Small, self-contained change
- No new features or architectural changes
- Clear fix for a specific problem
- Low risk of introducing regressions

**7. Similar Patterns:**
The comment in the fix mentions that "ext2_get_blocks() iterates
unmapped space block by block which is slow" - this suggests the min_t()
optimization is important for performance on large sparse files, but
shouldn't break functionality for empty files.

The fix properly balances maintaining the performance optimization while
ensuring correctness for the edge case of empty files.

 fs/ext2/inode.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 314b415ee518..6ff1f8f29a3c 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -895,9 +895,19 @@ int ext2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
 		u64 start, u64 len)
 {
 	int ret;
+	loff_t i_size;
 
 	inode_lock(inode);
-	len = min_t(u64, len, i_size_read(inode));
+	i_size = i_size_read(inode);
+	/*
+	 * iomap_fiemap() returns EINVAL for 0 length. Make sure we don't trim
+	 * length to 0 but still trim the range as much as possible since
+	 * ext2_get_blocks() iterates unmapped space block by block which is
+	 * slow.
+	 */
+	if (i_size == 0)
+		i_size = 1;
+	len = min_t(u64, len, i_size);
 	ret = iomap_fiemap(inode, fieinfo, start, len, &ext2_iomap_ops);
 	inode_unlock(inode);
 
-- 
2.39.5


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ