[PATCH v3 1/6] qnx6: validate di_filelevels in qnx6_iget() before accessing level pointers
From: Hui Peng
Date: Thu Sep 24 2026 - 03:43:40 EST
In qnx6_iget(), raw_inode->di_filelevels is read directly from the disk
image and stored into qnx6_inode->di_filelevels without checking if it
exceeds QNX6_PTR_MAX_LEVELS (3). If a corrupted disk image contains
di_filelevels > 3, subsequent file operations using qnx6_block_map()
access qnx6_inode->di_ptr[] past its array bound, causing out-of-bounds
reads and memory corruption.
Validate raw_inode->di_filelevels <= QNX6_PTR_MAX_LEVELS in qnx6_iget()
and return -EIO on corrupt inodes.
Fixes: 5d026c724220 ("fs: initial qnx6fs addition")
Cc: stable@xxxxxxxxxxxxxxx
Tested-by: Matthias Goergens <matthias.goergens@xxxxxxxxx>
Reviewed-by: Matthias Goergens <matthias.goergens@xxxxxxxxx>
Assisted-by: LLM
Signed-off-by: Hui Peng <benquike@xxxxxxxxx>
---
Changes in v3:
- Add Tested-by and Reviewed-by tags from Matthias Goergens.
- Update Fixes: tag SHA to 5d026c724220 ("fs: initial qnx6fs addition").
Changes in v2:
- Split out as patch 1/6 as requested by maintainers.
fs/qnx6/inode.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/fs/qnx6/inode.c b/fs/qnx6/inode.c
index a15c4de4f794..e1981e4ae47d 100644
--- a/fs/qnx6/inode.c
+++ b/fs/qnx6/inode.c
@@ -547,6 +547,11 @@ struct inode *qnx6_iget(struct super_block *sb, unsigned ino)
qnx6_inode->di_filelevels = raw_inode->di_filelevels;
qnx6_inode->di_status = raw_inode->di_status;
+ if (qnx6_inode->di_filelevels > QNX6_PTR_MAX_LEVELS) {
+ pr_err("invalid di_filelevels %u\n", qnx6_inode->di_filelevels);
+ iget_failed(inode);
+ return ERR_PTR(-EIO);
+ }
if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode)) {
memcpy(qnx6_inode->di_ptr, raw_inode->di_ptr,
sizeof(qnx6_inode->di_ptr));
--
2.55.0.1082.g2b9226bbc0-goog