Skip to content

Commit 4664fb4

Browse files
committed
Merge tag 'vfs-6.19-rc1.minix' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
Pull minix fixes from Christian Brauner: "Fix two syzbot corruption bugs in the minix filesystem. Syzbot fuzzes filesystems by trying to mount and manipulate deliberately corrupted images. This should not lead to BUG_ONs and WARN_ONs for easy to detect corruptions. - Add error handling to minix filesystem for inode corruption detection, enabling the filesystem to report such corruptions cleanly. - Fix a drop_nlink warning in minix_rmdir() triggered by corrupted directory link counts. - Fix a drop_nlink warning in minix_rename() triggered by corrupted inode link counts" * tag 'vfs-6.19-rc1.minix' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: Fix a drop_nlink warning in minix_rename Fix a drop_nlink warning in minix_rmdir Add error handling to minix filesystem for inode corruption detection
2 parents 978d337 + 0d53451 commit 4664fb4

3 files changed

Lines changed: 57 additions & 7 deletions

File tree

fs/minix/inode.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,22 @@ static int minix_write_inode(struct inode *inode,
2626
struct writeback_control *wbc);
2727
static int minix_statfs(struct dentry *dentry, struct kstatfs *buf);
2828

29+
void __minix_error_inode(struct inode *inode, const char *function,
30+
unsigned int line, const char *fmt, ...)
31+
{
32+
struct va_format vaf;
33+
va_list args;
34+
35+
va_start(args, fmt);
36+
vaf.fmt = fmt;
37+
vaf.va = &args;
38+
printk(KERN_CRIT "minix-fs error (device %s): %s:%d: "
39+
"inode #%lu: comm %s: %pV\n",
40+
inode->i_sb->s_id, function, line, inode->i_ino,
41+
current->comm, &vaf);
42+
va_end(args);
43+
}
44+
2945
static void minix_evict_inode(struct inode *inode)
3046
{
3147
truncate_inode_pages_final(&inode->i_data);

fs/minix/minix.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ struct minix_sb_info {
4242
unsigned short s_version;
4343
};
4444

45+
void __minix_error_inode(struct inode *inode, const char *function,
46+
unsigned int line, const char *fmt, ...);
47+
4548
struct inode *minix_iget(struct super_block *, unsigned long);
4649
struct minix_inode *minix_V1_raw_inode(struct super_block *, ino_t, struct buffer_head **);
4750
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)
168171

169172
#endif
170173

174+
#define minix_error_inode(inode, fmt, ...) \
175+
__minix_error_inode((inode), __func__, __LINE__, \
176+
(fmt), ##__VA_ARGS__)
177+
178+
#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */
179+
171180
#endif /* FS_MINIX_H */

fs/minix/namei.c

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,11 @@ static int minix_unlink(struct inode * dir, struct dentry *dentry)
145145
struct minix_dir_entry * de;
146146
int err;
147147

148+
if (inode->i_nlink == 0) {
149+
minix_error_inode(inode, "inode has corrupted nlink");
150+
return -EFSCORRUPTED;
151+
}
152+
148153
de = minix_find_entry(dentry, &folio);
149154
if (!de)
150155
return -ENOENT;
@@ -161,15 +166,24 @@ static int minix_unlink(struct inode * dir, struct dentry *dentry)
161166
static int minix_rmdir(struct inode * dir, struct dentry *dentry)
162167
{
163168
struct inode * inode = d_inode(dentry);
164-
int err = -ENOTEMPTY;
169+
int err = -EFSCORRUPTED;
165170

166-
if (minix_empty_dir(inode)) {
167-
err = minix_unlink(dir, dentry);
168-
if (!err) {
169-
inode_dec_link_count(dir);
170-
inode_dec_link_count(inode);
171-
}
171+
if (dir->i_nlink <= 2) {
172+
minix_error_inode(dir, "inode has corrupted nlink");
173+
goto out;
174+
}
175+
176+
err = -ENOTEMPTY;
177+
if (!minix_empty_dir(inode))
178+
goto out;
179+
180+
err = minix_unlink(dir, dentry);
181+
if (!err) {
182+
inode_dec_link_count(dir);
183+
inode_dec_link_count(inode);
172184
}
185+
186+
out:
173187
return err;
174188
}
175189

@@ -208,6 +222,17 @@ static int minix_rename(struct mnt_idmap *idmap,
208222
if (dir_de && !minix_empty_dir(new_inode))
209223
goto out_dir;
210224

225+
err = -EFSCORRUPTED;
226+
if (new_inode->i_nlink == 0 || (dir_de && new_inode->i_nlink != 2)) {
227+
minix_error_inode(new_inode, "inode has corrupted nlink");
228+
goto out_dir;
229+
}
230+
231+
if (dir_de && old_dir->i_nlink <= 2) {
232+
minix_error_inode(old_dir, "inode has corrupted nlink");
233+
goto out_dir;
234+
}
235+
211236
err = -ENOENT;
212237
new_de = minix_find_entry(new_dentry, &new_folio);
213238
if (!new_de)

0 commit comments

Comments
 (0)