mirror of https://github.com/torvalds/linux.git
vfs-6.19-rc1.minix
-----BEGIN PGP SIGNATURE-----
iHUEABYKAB0WIQRAhzRXHqcMeLMyaSiRxhvAZXjcogUCaSmOZgAKCRCRxhvAZXjc
olEcAP4qG313oT/tm4W3nC4g2k8S//KqET97B80pSX0K3DvQEwD+LSCf1Th3RnsV
EAMHczmCtRlbcFPqYOFVAMS8VxOyVg0=
=7Ca4
-----END PGP SIGNATURE-----
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
This commit is contained in:
commit
4664fb427c
|
|
@ -26,6 +26,22 @@ static int minix_write_inode(struct inode *inode,
|
||||||
struct writeback_control *wbc);
|
struct writeback_control *wbc);
|
||||||
static int minix_statfs(struct dentry *dentry, struct kstatfs *buf);
|
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)
|
static void minix_evict_inode(struct inode *inode)
|
||||||
{
|
{
|
||||||
truncate_inode_pages_final(&inode->i_data);
|
truncate_inode_pages_final(&inode->i_data);
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,9 @@ struct minix_sb_info {
|
||||||
unsigned short s_version;
|
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 inode *minix_iget(struct super_block *, unsigned long);
|
||||||
struct minix_inode *minix_V1_raw_inode(struct super_block *, ino_t, struct buffer_head **);
|
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 **);
|
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
|
#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 */
|
#endif /* FS_MINIX_H */
|
||||||
|
|
|
||||||
|
|
@ -145,6 +145,11 @@ static int minix_unlink(struct inode * dir, struct dentry *dentry)
|
||||||
struct minix_dir_entry * de;
|
struct minix_dir_entry * de;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
if (inode->i_nlink == 0) {
|
||||||
|
minix_error_inode(inode, "inode has corrupted nlink");
|
||||||
|
return -EFSCORRUPTED;
|
||||||
|
}
|
||||||
|
|
||||||
de = minix_find_entry(dentry, &folio);
|
de = minix_find_entry(dentry, &folio);
|
||||||
if (!de)
|
if (!de)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
@ -161,15 +166,24 @@ static int minix_unlink(struct inode * dir, struct dentry *dentry)
|
||||||
static int minix_rmdir(struct inode * dir, struct dentry *dentry)
|
static int minix_rmdir(struct inode * dir, struct dentry *dentry)
|
||||||
{
|
{
|
||||||
struct inode * inode = d_inode(dentry);
|
struct inode * inode = d_inode(dentry);
|
||||||
int err = -ENOTEMPTY;
|
int err = -EFSCORRUPTED;
|
||||||
|
|
||||||
if (minix_empty_dir(inode)) {
|
if (dir->i_nlink <= 2) {
|
||||||
err = minix_unlink(dir, dentry);
|
minix_error_inode(dir, "inode has corrupted nlink");
|
||||||
if (!err) {
|
goto out;
|
||||||
inode_dec_link_count(dir);
|
|
||||||
inode_dec_link_count(inode);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -208,6 +222,17 @@ static int minix_rename(struct mnt_idmap *idmap,
|
||||||
if (dir_de && !minix_empty_dir(new_inode))
|
if (dir_de && !minix_empty_dir(new_inode))
|
||||||
goto out_dir;
|
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;
|
err = -ENOENT;
|
||||||
new_de = minix_find_entry(new_dentry, &new_folio);
|
new_de = minix_find_entry(new_dentry, &new_folio);
|
||||||
if (!new_de)
|
if (!new_de)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue