summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorRichard Genoud <richard.genoud@posteo.net>2020-11-03 12:11:06 +0100
committerTom Rini <trini@konsulko.com>2020-11-19 09:45:49 -0500
commitcd54591afd42c547f43a7d509862f20e09264cde (patch)
tree5f064ccefe356007b136b274b5da090b4f5cf124 /fs
parent01e71ec61ab84bcdd4df708f8930d5acf1c2674d (diff)
fs/squashfs: sqfs_search_dir: fix memory leaks
path, target, res, rem and sym_tokens were not free on error nor success. Reviewed-by: Joao Marcos Costa <jmcosta944@gmail.com> Signed-off-by: Richard Genoud <richard.genoud@posteo.net>
Diffstat (limited to 'fs')
-rw-r--r--fs/squashfs/sqfs.c64
1 files changed, 51 insertions, 13 deletions
diff --git a/fs/squashfs/sqfs.c b/fs/squashfs/sqfs.c
index 78893b5c85..1714306e74 100644
--- a/fs/squashfs/sqfs.c
+++ b/fs/squashfs/sqfs.c
@@ -434,7 +434,7 @@ static int sqfs_search_dir(struct squashfs_dir_stream *dirs, char **token_list,
{
struct squashfs_super_block *sblk = ctxt.sblk;
char *path, *target, **sym_tokens, *res, *rem;
- int j, ret, new_inode_number, offset;
+ int j, ret = 0, new_inode_number, offset;
struct squashfs_symlink_inode *sym;
struct squashfs_ldir_inode *ldir;
struct squashfs_dir_inode *dir;
@@ -442,6 +442,12 @@ static int sqfs_search_dir(struct squashfs_dir_stream *dirs, char **token_list,
struct fs_dirent *dent;
unsigned char *table;
+ res = NULL;
+ rem = NULL;
+ path = NULL;
+ target = NULL;
+ sym_tokens = NULL;
+
dirsp = (struct fs_dir_stream *)dirs;
/* Start by root inode */
@@ -477,7 +483,8 @@ static int sqfs_search_dir(struct squashfs_dir_stream *dirs, char **token_list,
for (j = 0; j < token_count; j++) {
if (!sqfs_is_dir(get_unaligned_le16(&dir->inode_type))) {
printf("** Cannot find directory. **\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
while (!sqfs_readdir(dirsp, &dent)) {
@@ -490,7 +497,8 @@ static int sqfs_search_dir(struct squashfs_dir_stream *dirs, char **token_list,
if (ret) {
printf("** Cannot find directory. **\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
/* Redefine inode as the found token */
@@ -507,40 +515,63 @@ static int sqfs_search_dir(struct squashfs_dir_stream *dirs, char **token_list,
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;
+ }
/* Join remaining tokens */
rem = sqfs_concat_tokens(token_list + j + 1, token_count -
j - 1);
+ if (!rem) {
+ ret = -ENOMEM;
+ goto out;
+ }
/* Concatenate remaining tokens and symlink's target */
res = malloc(strlen(rem) + strlen(target) + 1);
+ if (!res) {
+ ret = -ENOMEM;
+ goto out;
+ }
strcpy(res, target);
res[strlen(target)] = '/';
strcpy(res + strlen(target) + 1, rem);
token_count = sqfs_count_tokens(res);
- if (token_count < 0)
- return -EINVAL;
+ if (token_count < 0) {
+ ret = -EINVAL;
+ goto out;
+ }
sym_tokens = malloc(token_count * sizeof(char *));
- if (!sym_tokens)
- return -EINVAL;
+ if (!sym_tokens) {
+ ret = -EINVAL;
+ goto out;
+ }
/* Fill tokens list */
ret = sqfs_tokenize(sym_tokens, token_count, res);
- if (ret)
- return -EINVAL;
+ if (ret) {
+ ret = -EINVAL;
+ goto out;
+ }
free(dirs->entry);
dirs->entry = NULL;
ret = sqfs_search_dir(dirs, sym_tokens, token_count,
m_list, m_count);
- return ret;
+ goto out;
} else if (!sqfs_is_dir(get_unaligned_le16(&dir->inode_type))) {
printf("** Cannot find directory. **\n");
free(dirs->entry);
dirs->entry = NULL;
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
/* Check if it is an extended dir. */
@@ -560,7 +591,8 @@ static int sqfs_search_dir(struct squashfs_dir_stream *dirs, char **token_list,
printf("Empty directory.\n");
free(dirs->entry);
dirs->entry = NULL;
- return SQFS_EMPTY_DIR;
+ ret = SQFS_EMPTY_DIR;
+ goto out;
}
dirs->table += SQFS_DIR_HEADER_SIZE;
@@ -579,7 +611,13 @@ static int sqfs_search_dir(struct squashfs_dir_stream *dirs, char **token_list,
else
memcpy(&dirs->i_ldir, ldir, sizeof(*ldir));
- return 0;
+out:
+ free(res);
+ free(rem);
+ free(path);
+ free(target);
+ free(sym_tokens);
+ return ret;
}
/*