The three directory-search loops in sqfs.c use the local `ret` to tell whether the requested name was found. When the loop runs zero times `ret` keeps the 0 left by the preceding sqfs_opendir_nest(), so the "not found" check is skipped and the NULL dirs->entry is dereferenced (dirs->entry->inode_offset). A crafted or corrupted image can thus crash U-Boot (a NULL read) while resolving, reading or sizing a path.
Treat a loop that produced no entry as "not found" in sqfs_search_dir(), sqfs_read_nest() and sqfs_size_nest(). Found by fuzzing the SquashFS parser. Signed-off-by: Oscar Deschamps <[email protected]> --- fs/squashfs/sqfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/squashfs/sqfs.c b/fs/squashfs/sqfs.c index 0ea6dcaba1a..c8d2ade83e4 100644 --- a/fs/squashfs/sqfs.c +++ b/fs/squashfs/sqfs.c @@ -581,7 +581,7 @@ static int sqfs_search_dir(struct squashfs_dir_stream *dirs, char **token_list, dirs->entry = NULL; } - if (ret) { + if (ret || !dirs->entry) { printf("** Cannot find directory. **\n"); ret = -EINVAL; goto out; @@ -1501,7 +1501,7 @@ static int sqfs_read_nest(const char *filename, void *buf, loff_t offset, dirs->entry = NULL; } - if (ret) { + if (ret || !dirs->entry) { printf("File not found.\n"); *actread = 0; ret = -ENOENT; @@ -1803,7 +1803,7 @@ static int sqfs_size_nest(const char *filename, loff_t *size) dirs->entry = NULL; } - if (ret) { + if (ret || !dirs->entry) { printf("File not found.\n"); *size = 0; ret = -EINVAL; -- 2.43.0
