atement added to `hfsplus_system_read_inode()` in `fs/hfsplus/super.c`: ```c inode->i_mode = S_IFREG; ``` This is placed after the switch statement that reads the fork data for each special inode type (HFSPLUS_EXT_CNID, HFSPLUS_CAT_CNID, HFSPLUS_ALLOC_CNID, HFSPLUS_START_CNID, HFSPLUS_ATTR_CNID). **The bug mechanism**: When `hfsplus_iget()` is called for a system inode (inode number < `HFSPLUS_FIRSTUSER_CNID` and != `HFSPLUS_ROOT_CNID`), it calls `hfsplus_system_read_inode()`. This function sets up the fork data and address space operations but **never sets `i_mode`**. The `i_mode` remains 0 (the default from `iget_locked()` → `alloc_inode()`). Zero is not a valid file type - it doesn't match any of S_IFDIR, S_IFLNK, S_IFREG, S_IFCHR, S_IFBLK, S_IFIFO, or S_IFSOCK. When this inode is later opened via a userspace `openat()` syscall (triggered by syzbot with a crafted filesystem), `may_open()` is called: ```4175:4232:fs/namei.c static int may_open(struct mnt_idmap *idmap, const struct path *path, int acc_mode, int flag) { // ... switch (inode->i_mode & S_IFMT) { case S_IFLNK: // ... case S_IFREG: // ... default: VFS_BUG_ON_INODE(!IS_ANON_FILE(inode), inode); } ``` With `i_mode = 0`, the switch falls to the default case, and since HFS+ special inodes aren't anonymous files, `VFS_BUG_ON_INODE` triggers → **kernel BUG** (crash). This is confirmed by the syzbot crash report showing `kernel BUG at fs/namei.c:3474` with a full stack trace through `may_open` → `do_open` → `path_openat` → `do_filp_open` → `do_sys_openat2` → `__x64_sys_openat`. ### 3. Relationship to Other Fixes This is **NOT a duplicate** of `005d4b0d33f6` ("hfsplus: Verify inode mode when loading from disk"). That fix addresses a DIFFERENT code path: - `005d4b0d33f6` fixes `hfsplus_get_perms()` in `fs/hfsplus/inode.c` - validates mode for **user/root inodes** loaded from disk (corrupted on-disk mode) - The commit we're analyzing fixes `hfsplus_system_read_inode()` in `fs/hfsplus/super.c` - sets mode for **special/system inodes** that never go through `hfsplus_get_perms()` at all In `hfsplus_iget()`, the two paths are clearly separated: - `inode->i_ino >= HFSPLUS_FIRSTUSER_CNID || inode->i_ino == HFSPLUS_ROOT_CNID` → `hfsplus_cat_read_inode()` → `hfsplus_get_perms()` (fixed by `005d4b0d33f6`) - Otherwise → `hfsplus_system_read_inode()` (fixed by THIS commit) Confirmed via grep: there is literally NO `i_mode` reference in `fs/hfsplus/super.c` currently. ### 4. CONFIG_DEBUG_VFS Dependency The `VFS_BUG_ON_INODE` macro is only active when `CONFIG_DEBUG_VFS` is enabled. Without it, it's compiled to `BUILD_BUG_ON_INVALID(cond)` which is a no-op at runtime. `CONFIG_DEBUG_VFS` was introduced alongside `af153bb63a33` in v6.15 (commit `8b17e540969a`). So the **crash** only occurs on kernels 6.15+ with `CONFIG_DEBUG_VFS` enabled. However, having `i_mode = 0` is technically incorrect on ALL kernel versions - any code checking inode type would get wrong results for these inodes. ### 5. Scope and Risk Assessment - **Lines changed**: 6 (including comment) - effectively 1 functional line - **Files touched**: 1 (`fs/hfsplus/super.c`) - **Risk**: Essentially zero. Setting `S_IFREG` on internal filesystem inodes that previously had no type is strictly an improvement. These inodes are filesystem metadata (btrees, allocation bitmap) - they are file-like data structures, so `S_IFREG` is appropriate. - **No behavioral regression**: The fix doesn't change how the filesystem operates; it only ensures the inode has a valid VFS-level type. ### 6. User Impact - **Who's affected**: Anyone mounting HFS+ filesystems on kernels 6.15+ with `CONFIG_DEBUG_VFS` - **Severity**: Kernel BUG/crash - system goes down - **Trigger**: syzbot demonstrated this with crafted filesystem images, but it could potentially also be triggered with corrupted real HFS+ volumes - **syzbot confirmed**: 17,716 crashes recorded, reproducible with C reproducer ### 7. Stability Indicators - Reviewed-by: Viacheslav Dubeyko (HFS+ maintainer) - Signed-off-by: Viacheslav Dubeyko (maintainer) - syzbot reported with concrete reproducer - Part of a series of similar fixes across multiple filesystems (bfs, cramfs, isofs, jfs, minixfs, nilfs2, ntfs3, squashfs) - the ntfs3 equivalent `4e8011ffec79` is already merged ### 8. Dependencies The prerequisite VFS commit `af153bb63a33` exists in 6.15+. For older stable trees (6.14 and below), the `VFS_BUG_ON_INODE` doesn't exist, so the crash won't happen. However, the fix itself applies cleanly regardless of version since `hfsplus_system_read_inode()` has been stable for many years. Setting a proper i_mode is correct behavior independently of the VFS debug check. ### Conclusion This is a clear **YES** for stable backporting: - Fixes a syzbot-reported kernel BUG (crash) - 17,716 crash instances recorded - The fix is one functional line: `inode->i_mode = S_IFREG;` - Zero risk of regression - Obviously correct - internal inodes should have a valid file type - Reviewed and accepted by the subsystem maintainer - Complements the already-merged `005d4b0d33f6` by covering a different code path - Part of a broader class of fixes across multiple filesystems for the same VFS requirement **YES** fs/hfsplus/super.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index aaffa9e060a0a..7f327b777ece8 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -53,6 +53,12 @@ static int hfsplus_system_read_inode(struct inode *inode) return -EIO; } + /* + * Assign a dummy file type, for may_open() requires that + * an inode has a valid file type. + */ + inode->i_mode = S_IFREG; + return 0; } -- 2.51.0[PATCH AUTOSEL 6.19-5.10] hfsplus: pretend special inodes as regular filesSasha Levin undefinedpatches@lists.linux.dev, stable@vger.kernel.org undefined undefined undefined undefined undefined undefined undefinedÐ#…ò