From: Yangtao Li frank.li@vivo.com
[ Upstream commit 9282bc905f0949fab8cf86c0f620ca988761254c ]
If Catalog File contains corrupted record for the case of hidden directory's type, regard it as I/O error instead of Invalid argument.
Signed-off-by: Yangtao Li frank.li@vivo.com Reviewed-by: Viacheslav Dubeyko slava@dubeyko.com Link: https://lore.kernel.org/r/20250805165905.3390154-1-frank.li@vivo.com Signed-off-by: Viacheslav Dubeyko slava@dubeyko.com Signed-off-by: Sasha Levin sashal@kernel.org ---
LLM Generated explanations, may be completely bogus:
Based on my extensive analysis, here is my comprehensive assessment:
## Backport Status: YES
## Detailed Analysis
### 1. Historical Context
Through git history analysis, I discovered that the `-EINVAL` error code was introduced in **2018 by Tetsuo Handa** (commit 7464726cb5998) to fix a critical syzbot-reported bug where `hfsplus_fill_super()` was returning 0 (success) when detecting invalid filesystem images, causing NULL pointer dereferences. The choice of `-EINVAL` was somewhat arbitrary—the primary goal was to return *any* error instead of 0.
### 2. What This Commit Fixes
This commit corrects the error semantics at fs/hfsplus/super.c:527, changing from `-EINVAL` to `-EIO` when the hidden directory's catalog entry has an incorrect type (not `HFSPLUS_FOLDER`). This is filesystem metadata corruption, not invalid user input.
### 3. Code Pattern Analysis
Examining the HFS+ codebase reveals a clear pattern: - **-EIO usage**: 27+ instances across super.c, btree.c, xattr.c, dir.c, catalog.c, etc., consistently used for on-disk corruption - **-EINVAL usage**: Used for invalid mount options (options.c) and invalid user-provided arguments - **Line 527 was the exception**: It incorrectly used `-EINVAL` for what is clearly filesystem corruption
This pattern is consistent with other filesystems: NILFS2 extensively documents "`-EIO` - I/O error (including metadata corruption)" while reserving `-EINVAL` for invalid arguments.
### 4. Backport Suitability Assessment
**Strongly Suitable:** - ✅ **Semantic correctness fix**: Aligns error handling with established kernel patterns - ✅ **Minimal risk**: Single-line change affecting only error code returned - ✅ **No functional changes**: Doesn't alter any logic, just error semantics - ✅ **Improves consistency**: Brings this code in line with rest of HFS+ subsystem - ✅ **Benefits users**: More accurate error reporting for corrupted filesystems - ✅ **Already reviewed**: Reviewed-by: Viacheslav Dubeyko (HFS+ maintainer) - ✅ **No architectural changes**: Confined to error handling - ✅ **No user-space dependencies**: Mount utilities don't depend on specific error codes
### 5. Evidence of Active Backporting
The commit has **ALREADY been backported** to stable trees: - Commit 22017d3bff896 shows `[ Upstream commit 9282bc905f0949fab8cf86c0f620ca988761254c ]` - Signed-off-by: Sasha Levin for stable tree inclusion - CommitDate: Sep 30, 2025 (present in linux-autosel-6.17-2)
### 6. Context Within Broader HFS+ Hardening
Recent HFS+ commits show active efforts to improve robustness against corrupted/malicious filesystem images: - Multiple KMSAN uninit-value fixes - Slab-out-of-bounds fixes - Removal of BUG_ON() in favor of graceful error handling - Validation improvements for record offsets
This commit is part of that broader hardening effort.
### 7. Risk Assessment
**Regression Risk: MINIMAL** - Only changes the errno value returned during mount failure - User-space tools (mount, fsck.hfsplus) display different error messages but behavior is unchanged - No security implications—both error codes indicate mount failure - Cannot affect successfully mounted filesystems
**Recommendation:** This commit should be backported to all maintained stable kernels where the original `-EINVAL` code exists (approximately since Linux 2.6.x, but practically important for kernels 4.x+).
fs/hfsplus/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 2f215d1daf6d9..77ec048021a01 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -537,7 +537,7 @@ static int hfsplus_fill_super(struct super_block *sb, struct fs_context *fc) if (!hfs_brec_read(&fd, &entry, sizeof(entry))) { hfs_find_exit(&fd); if (entry.type != cpu_to_be16(HFSPLUS_FOLDER)) { - err = -EINVAL; + err = -EIO; goto out_put_root; } inode = hfsplus_iget(sb, be32_to_cpu(entry.folder.id));