If the directory is corrupted and the number of nlinks is less than 2 (valid nlinks have at least 2), then when the directory is deleted, the minix_rmdir will try to reduce the nlinks(unsigned int) to a negative value.
Make nlinks validity check for directory in minix_lookup.
Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: stable@vger.kernel.org Signed-off-by: Andrey Kriulin kitotavrik.media@gmail.com --- fs/minix/namei.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/fs/minix/namei.c b/fs/minix/namei.c index 8938536d8..5717a56fa 100644 --- a/fs/minix/namei.c +++ b/fs/minix/namei.c @@ -28,8 +28,13 @@ static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, un return ERR_PTR(-ENAMETOOLONG);
ino = minix_inode_by_name(dentry); - if (ino) + if (ino) { inode = minix_iget(dir->i_sb, ino); + if (S_ISDIR(inode->i_mode) && inode->i_nlink < 2) { + iput(inode); + return ERR_PTR(-EIO); + } + } return d_splice_alias(inode, dentry); }
On Fri 02-05-25 19:43:36, Andrey Kriulin wrote:
If the directory is corrupted and the number of nlinks is less than 2 (valid nlinks have at least 2), then when the directory is deleted, the minix_rmdir will try to reduce the nlinks(unsigned int) to a negative value.
Make nlinks validity check for directory in minix_lookup.
Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: stable@vger.kernel.org Signed-off-by: Andrey Kriulin kitotavrik.media@gmail.com
Thanks for the patch. One comment below.
diff --git a/fs/minix/namei.c b/fs/minix/namei.c index 8938536d8..5717a56fa 100644 --- a/fs/minix/namei.c +++ b/fs/minix/namei.c @@ -28,8 +28,13 @@ static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, un return ERR_PTR(-ENAMETOOLONG); ino = minix_inode_by_name(dentry);
- if (ino)
- if (ino) { inode = minix_iget(dir->i_sb, ino);
if (S_ISDIR(inode->i_mode) && inode->i_nlink < 2) {
iput(inode);
return ERR_PTR(-EIO);
}
- } return d_splice_alias(inode, dentry);
}
I don't think this is the best place to handle such check. IMO it would be more logical to do it in minix_iget() - V[12]_minix_iget() to be more precise - to properly catch all the paths where the inode is loaded into memory. This way your check will not happen for the root directory inode for example.
Honza
linux-stable-mirror@lists.linaro.org