[PATCH v2 3/3] fs/squashfs: fix dirs->entry leak on inode lookup failure
Richard GENOUD
richard.genoud at bootlin.com
Wed Jun 24 17:23:59 CEST 2026
Le 11/06/2026 à 11:43, Allan ELKAIM a écrit :
> In sqfs_search_dir(), when sqfs_find_inode() fails to locate the inode
> of a directory entry just returned by sqfs_readdir_nest(), the function
> returns directly while dirs->entry still holds the entry allocation,
> leaking it. The bare return also bypasses the regular error path.
>
> Free the entry and leave through the out label instead, consistent
> with the other error paths in this function.
>
> Signed-off-by: Allan ELKAIM <allan.elkaim at gmail.com>
> ---
>
> Changes in v2:
> - New patch, fixing a pre-existing leak of the same kind as the ones
> addressed in patch 2 (suggested by Richard Genoud's review)
>
> fs/squashfs/sqfs.c | 8 ++++++--
> 1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/fs/squashfs/sqfs.c b/fs/squashfs/sqfs.c
> index af32d008..df988774 100644
> --- a/fs/squashfs/sqfs.c
> +++ b/fs/squashfs/sqfs.c
> @@ -547,8 +547,12 @@ static int sqfs_search_dir(struct squashfs_dir_stream *dirs, char **token_list,
> /* Get reference to inode in the inode table */
> table = sqfs_find_inode(dirs->inode_table, new_inode_number,
> sblk->inodes, sblk->block_size);
> - if (!table)
> - return -EINVAL;
> + if (!table) {
> + free(dirs->entry);
> + dirs->entry = NULL;
> + ret = -EINVAL;
> + goto out;
> + }
> dir = (struct squashfs_dir_inode *)table;
>
> /* Check for symbolic link and inode type sanity */
Having a 2nd look at the whole function, it seems that there a lot of:
ret = -Exxx;
goto out;
without freeing dirs->entry
Like here:
[...]
if (++symlinknest == MAX_SYMLINK_NEST) {
ret = -ELOOP;
goto out;
}
sym = (struct squashfs_symlink_inode *)table;
/* Get first j + 1 tokens */
path = sqfs_concat_tokens(token_list, j + 1);
if (!path) {
ret = -ENOMEM;
goto out;
}
/* Resolve for these tokens */
target = sqfs_resolve_symlink(sym, path);
if (!target) {
ret = -ENOMEM;
goto out;
}
[...]
It seems to me that we could keep free(dirs->entry):
- in the while (!sqfs_readdir_nest(dirsp, &dent)) loop
- at the end of the for (j = 0; j < token_count; j++) loop
- and before the recursive call to sqfs_search_dir()
And remove all the rest to add something like:
@@ -677,6 +677,10 @@ static int sqfs_search_dir(struct squashfs_dir_stream *dirs, char **token_list,
memcpy(&dirs->i_ldir, ldir, sizeof(*ldir));
out:
+ if (ret < 0) {
+ free(dirs->entry);
+ dirs->entry = NULL;
+ }
free(res);
free(rem);
free(path);
(not tested)
What do you think?
Regards,
Richard
More information about the U-Boot
mailing list