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

Reply via email to