From 7a5aa54fba2bd591b22b9b624e6baa9037276986 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Fri, 12 Sep 2025 23:18:44 +0900 Subject: [PATCH 1/5] jfs: Verify inode mode when loading from disk The inode mode loaded from corrupted disk can be invalid. Do like what commit 0a9e74051313 ("isofs: Verify inode mode when loading from disk") does. Reported-by: syzbot Closes: https://syzkaller.appspot.com/bug?extid=895c23f6917da440ed0d Signed-off-by: Tetsuo Handa Signed-off-by: Dave Kleikamp --- fs/jfs/inode.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c index fcedeb514e14..21f3d029da7d 100644 --- a/fs/jfs/inode.c +++ b/fs/jfs/inode.c @@ -59,9 +59,15 @@ struct inode *jfs_iget(struct super_block *sb, unsigned long ino) */ inode->i_link[inode->i_size] = '\0'; } - } else { + } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || + S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { inode->i_op = &jfs_file_inode_operations; init_special_inode(inode, inode->i_mode, inode->i_rdev); + } else { + printk(KERN_DEBUG "JFS: Invalid file type 0%04o for inode %lu.\n", + inode->i_mode, inode->i_ino); + iget_failed(inode); + return ERR_PTR(-EIO); } unlock_new_inode(inode); return inode; From 300b072df72694ea330c4c673c035253e07827b8 Mon Sep 17 00:00:00 2001 From: Shaurya Rane Date: Mon, 25 Aug 2025 01:43:32 +0530 Subject: [PATCH 2/5] jfs: fix uninitialized waitqueue in transaction manager The transaction manager initialization in txInit() was not properly initializing TxBlock[0].waitor waitqueue, causing a crash when txEnd(0) is called on read-only filesystems. When a filesystem is mounted read-only, txBegin() returns tid=0 to indicate no transaction. However, txEnd(0) still gets called and tries to access TxBlock[0].waitor via tid_to_tblock(0), but this waitqueue was never initialized because the initialization loop started at index 1 instead of 0. This causes a 'non-static key' lockdep warning and system crash: INFO: trying to register non-static key in txEnd Fix by ensuring all transaction blocks including TxBlock[0] have their waitqueues properly initialized during txInit(). Reported-by: syzbot+c4f3462d8b2ad7977bea@syzkaller.appspotmail.com Signed-off-by: Shaurya Rane Signed-off-by: Dave Kleikamp --- fs/jfs/jfs_txnmgr.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c index be17e3c43582..7840a03e5bcb 100644 --- a/fs/jfs/jfs_txnmgr.c +++ b/fs/jfs/jfs_txnmgr.c @@ -272,14 +272,15 @@ int txInit(void) if (TxBlock == NULL) return -ENOMEM; - for (k = 1; k < nTxBlock - 1; k++) { - TxBlock[k].next = k + 1; + for (k = 0; k < nTxBlock; k++) { init_waitqueue_head(&TxBlock[k].gcwait); init_waitqueue_head(&TxBlock[k].waitor); } + + for (k = 1; k < nTxBlock - 1; k++) { + TxBlock[k].next = k + 1; + } TxBlock[k].next = 0; - init_waitqueue_head(&TxBlock[k].gcwait); - init_waitqueue_head(&TxBlock[k].waitor); TxAnchor.freetid = 1; init_waitqueue_head(&TxAnchor.freewait); From 69f7321ce7250b779e7ff2f20d330987c966000a Mon Sep 17 00:00:00 2001 From: Liao Yuanhong Date: Mon, 25 Aug 2025 21:36:49 +0800 Subject: [PATCH 3/5] JFS: Remove unnecessary parentheses When using &, it's unnecessary to have parentheses afterward. Remove redundant parentheses to enhance readability. Signed-off-by: Liao Yuanhong Signed-off-by: Dave Kleikamp --- fs/jfs/jfs_mount.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/jfs/jfs_mount.c b/fs/jfs/jfs_mount.c index 98f9a432c336..52e6b58c5dbd 100644 --- a/fs/jfs/jfs_mount.c +++ b/fs/jfs/jfs_mount.c @@ -325,13 +325,13 @@ static int chkSuper(struct super_block *sb) if ((j_sb->s_flag & cpu_to_le32(JFS_BAD_SAIT)) != cpu_to_le32(JFS_BAD_SAIT)) { expected_AIM_bytesize = 2 * PSIZE; - AIM_bytesize = lengthPXD(&(j_sb->s_aim2)) * bsize; + AIM_bytesize = lengthPXD(&j_sb->s_aim2) * bsize; expected_AIT_bytesize = 4 * PSIZE; - AIT_bytesize = lengthPXD(&(j_sb->s_ait2)) * bsize; - AIM_byte_addr = addressPXD(&(j_sb->s_aim2)) * bsize; - AIT_byte_addr = addressPXD(&(j_sb->s_ait2)) * bsize; + AIT_bytesize = lengthPXD(&j_sb->s_ait2) * bsize; + AIM_byte_addr = addressPXD(&j_sb->s_aim2) * bsize; + AIT_byte_addr = addressPXD(&j_sb->s_ait2) * bsize; byte_addr_diff0 = AIT_byte_addr - AIM_byte_addr; - fsckwsp_addr = addressPXD(&(j_sb->s_fsckpxd)) * bsize; + fsckwsp_addr = addressPXD(&j_sb->s_fsckpxd) * bsize; byte_addr_diff1 = fsckwsp_addr - AIT_byte_addr; if ((AIM_bytesize != expected_AIM_bytesize) || (AIT_bytesize != expected_AIT_bytesize) || From e551cc21bb0bb3f0a776a012c6033ccd4cbe419e Mon Sep 17 00:00:00 2001 From: Liao Yuanhong Date: Tue, 19 Aug 2025 11:28:14 +0800 Subject: [PATCH 4/5] JFS: Remove redundant 0 value initialization The jfs_log struct is already zeroed by kzalloc(). It's redundant to initialize dummy_log->base to 0. Signed-off-by: Liao Yuanhong Signed-off-by: Dave Kleikamp --- fs/jfs/jfs_logmgr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c index 270808b6219b..b343c5ea1159 100644 --- a/fs/jfs/jfs_logmgr.c +++ b/fs/jfs/jfs_logmgr.c @@ -1199,7 +1199,6 @@ static int open_dummy_log(struct super_block *sb) init_waitqueue_head(&dummy_log->syncwait); dummy_log->no_integrity = 1; /* Make up some stuff */ - dummy_log->base = 0; dummy_log->size = 1024; rc = lmLogInit(dummy_log); if (rc) { From cafc6679824a026998d93e7435f6005f64e515d2 Mon Sep 17 00:00:00 2001 From: Zheng Yu Date: Tue, 29 Jul 2025 18:28:56 +0000 Subject: [PATCH 5/5] jfs: replace hardcoded magic number with DTPAGEMAXSLOT constant Replace hardcoded value 127 with DTPAGEMAXSLOT constant in boundary checks within jfs_readdir() and dtReadFirst(). This improves code maintainability and ensures consistency with the defined maximum slot value. Signed-off-by: Zheng Yu Signed-off-by: Dave Kleikamp --- fs/jfs/jfs_dtree.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c index ab11849cf9cc..0ab83bb7bbdf 100644 --- a/fs/jfs/jfs_dtree.c +++ b/fs/jfs/jfs_dtree.c @@ -2903,7 +2903,7 @@ int jfs_readdir(struct file *file, struct dir_context *ctx) stbl = DT_GETSTBL(p); for (i = index; i < p->header.nextindex; i++) { - if (stbl[i] < 0 || stbl[i] > 127) { + if (stbl[i] < 0 || stbl[i] >= DTPAGEMAXSLOT) { jfs_err("JFS: Invalid stbl[%d] = %d for inode %ld, block = %lld", i, stbl[i], (long)ip->i_ino, (long long)bn); free_page(dirent_buf); @@ -3108,7 +3108,7 @@ static int dtReadFirst(struct inode *ip, struct btstack * btstack) /* get the leftmost entry */ stbl = DT_GETSTBL(p); - if (stbl[0] < 0 || stbl[0] > 127) { + if (stbl[0] < 0 || stbl[0] >= DTPAGEMAXSLOT) { DT_PUTPAGE(mp); jfs_error(ip->i_sb, "stbl[0] out of bound\n"); return -EIO;