From 21215ce7a95ae03891708028a8c805e5dc47395e Mon Sep 17 00:00:00 2001 From: Jori Koolstra Date: Tue, 4 Nov 2025 15:30:03 +0100 Subject: [PATCH 1/3] Add error handling to minix filesystem for inode corruption detection We would like to provide early and specific warnings of filesystem corruption without running into generic WARN_ONs and BUG_ONs. Towards this goal, ext4, e.g., has a EFSCORRUPTED errno and a standardized inode corruption message format. This patch adds this errno and message format to the minix filesystem. Signed-off-by: Jori Koolstra Link: https://patch.msgid.link/20251104143005.3283980-2-jkoolstra@xs4all.nl Reviewed-by: Jan Kara Signed-off-by: Christian Brauner --- fs/minix/inode.c | 16 ++++++++++++++++ fs/minix/minix.h | 9 +++++++++ 2 files changed, 25 insertions(+) diff --git a/fs/minix/inode.c b/fs/minix/inode.c index 32db676127a9..7897f5123b3d 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -26,6 +26,22 @@ static int minix_write_inode(struct inode *inode, struct writeback_control *wbc); static int minix_statfs(struct dentry *dentry, struct kstatfs *buf); +void __minix_error_inode(struct inode *inode, const char *function, + unsigned int line, const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + va_start(args, fmt); + vaf.fmt = fmt; + vaf.va = &args; + printk(KERN_CRIT "minix-fs error (device %s): %s:%d: " + "inode #%lu: comm %s: %pV\n", + inode->i_sb->s_id, function, line, inode->i_ino, + current->comm, &vaf); + va_end(args); +} + static void minix_evict_inode(struct inode *inode) { truncate_inode_pages_final(&inode->i_data); diff --git a/fs/minix/minix.h b/fs/minix/minix.h index d54273c3c9ff..2bfaf377f208 100644 --- a/fs/minix/minix.h +++ b/fs/minix/minix.h @@ -42,6 +42,9 @@ struct minix_sb_info { unsigned short s_version; }; +void __minix_error_inode(struct inode *inode, const char *function, + unsigned int line, const char *fmt, ...); + struct inode *minix_iget(struct super_block *, unsigned long); struct minix_inode *minix_V1_raw_inode(struct super_block *, ino_t, struct buffer_head **); struct minix2_inode *minix_V2_raw_inode(struct super_block *, ino_t, struct buffer_head **); @@ -168,4 +171,10 @@ static inline int minix_test_bit(int nr, const void *vaddr) #endif +#define minix_error_inode(inode, fmt, ...) \ + __minix_error_inode((inode), __func__, __LINE__, \ + (fmt), ##__VA_ARGS__) + +#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */ + #endif /* FS_MINIX_H */ From d3e0e8661ceb4fe3aab85af3730dbf41240d561f Mon Sep 17 00:00:00 2001 From: Jori Koolstra Date: Tue, 4 Nov 2025 15:30:04 +0100 Subject: [PATCH 2/3] Fix a drop_nlink warning in minix_rmdir Syzbot found a drop_nlink warning that is triggered by an easy to detect nlink corruption of a directory. This patch adds a sanity check to minix_rmdir to prevent the warning and instead return EFSCORRUPTED to the caller. The changes were tested using the syzbot reproducer as well as local testing. Signed-off-by: Jori Koolstra Link: https://patch.msgid.link/20251104143005.3283980-3-jkoolstra@xs4all.nl Reviewed-by: Jan Kara Reported-by: syzbot+4e49728ec1cbaf3b91d2@syzkaller.appspotmail.com Closes: https://syzbot.org/bug?extid=4e49728ec1cbaf3b91d2 Signed-off-by: Christian Brauner --- fs/minix/namei.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/fs/minix/namei.c b/fs/minix/namei.c index 8938536d8d3c..68d2dd75b97f 100644 --- a/fs/minix/namei.c +++ b/fs/minix/namei.c @@ -161,15 +161,24 @@ static int minix_unlink(struct inode * dir, struct dentry *dentry) static int minix_rmdir(struct inode * dir, struct dentry *dentry) { struct inode * inode = d_inode(dentry); - int err = -ENOTEMPTY; + int err = -EFSCORRUPTED; - if (minix_empty_dir(inode)) { - err = minix_unlink(dir, dentry); - if (!err) { - inode_dec_link_count(dir); - inode_dec_link_count(inode); - } + if (dir->i_nlink <= 2) { + minix_error_inode(dir, "inode has corrupted nlink"); + goto out; } + + err = -ENOTEMPTY; + if (!minix_empty_dir(inode)) + goto out; + + err = minix_unlink(dir, dentry); + if (!err) { + inode_dec_link_count(dir); + inode_dec_link_count(inode); + } + +out: return err; } From 009a2ba40303cb1e3556c41233338e609ac509ea Mon Sep 17 00:00:00 2001 From: Jori Koolstra Date: Tue, 4 Nov 2025 15:30:05 +0100 Subject: [PATCH 3/3] Fix a drop_nlink warning in minix_rename Syzbot found a drop_nlink warning that is triggered by an easy to detect nlink corruption. This patch adds sanity checks to minix_unlink and minix_rename to prevent the warning and instead return EFSCORRUPTED to the caller. The changes were tested using the syzbot reproducer as well as local testing. Signed-off-by: Jori Koolstra Link: https://patch.msgid.link/20251104143005.3283980-4-jkoolstra@xs4all.nl Reviewed-by: Jan Kara Reported-by: syzbot+a65e824272c5f741247d@syzkaller.appspotmail.com Closes: https://syzbot.org/bug?extid=a65e824272c5f741247d Signed-off-by: Christian Brauner --- fs/minix/namei.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/fs/minix/namei.c b/fs/minix/namei.c index 68d2dd75b97f..263e4ba8b1c8 100644 --- a/fs/minix/namei.c +++ b/fs/minix/namei.c @@ -145,6 +145,11 @@ static int minix_unlink(struct inode * dir, struct dentry *dentry) struct minix_dir_entry * de; int err; + if (inode->i_nlink == 0) { + minix_error_inode(inode, "inode has corrupted nlink"); + return -EFSCORRUPTED; + } + de = minix_find_entry(dentry, &folio); if (!de) return -ENOENT; @@ -217,6 +222,17 @@ static int minix_rename(struct mnt_idmap *idmap, if (dir_de && !minix_empty_dir(new_inode)) goto out_dir; + err = -EFSCORRUPTED; + if (new_inode->i_nlink == 0 || (dir_de && new_inode->i_nlink != 2)) { + minix_error_inode(new_inode, "inode has corrupted nlink"); + goto out_dir; + } + + if (dir_de && old_dir->i_nlink <= 2) { + minix_error_inode(old_dir, "inode has corrupted nlink"); + goto out_dir; + } + err = -ENOENT; new_de = minix_find_entry(new_dentry, &new_folio); if (!new_de)