2022-01-04 12:09:20

by zhanchengbin

[permalink] [raw]
Subject: [PATCH v3] setup_tdb : fix memory leak

In setup_tdb(), need free tdb_dir and db->tdb_fn before return,
otherwise it will cause memory leak.

Signed-off-by: zhanchengbin <[email protected]>
Signed-off-by: Zhiqiang Liu <[email protected]>
Reviewed-by: Ritesh Harjani <[email protected]>
---
e2fsck/dirinfo.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/e2fsck/dirinfo.c b/e2fsck/dirinfo.c
index 49d624c5..5b1088d4 100644
--- a/e2fsck/dirinfo.c
+++ b/e2fsck/dirinfo.c
@@ -49,7 +49,7 @@ static void setup_tdb(e2fsck_t ctx, ext2_ino_t num_dirs)
ext2_ino_t threshold;
errcode_t retval;
mode_t save_umask;
- char *tdb_dir, uuid[40];
+ char *tdb_dir = NULL, uuid[40];
int fd, enable;

profile_get_string(ctx->profile, "scratch_files", "directory", 0, 0,
@@ -61,11 +61,11 @@ static void setup_tdb(e2fsck_t ctx, ext2_ino_t num_dirs)

if (!enable || !tdb_dir || access(tdb_dir, W_OK) ||
(threshold && num_dirs <= threshold))
- return;
+ goto tdb_dir_error;

retval = ext2fs_get_mem(strlen(tdb_dir) + 64, &db->tdb_fn);
if (retval)
- return;
+ goto tdb_dir_error;

uuid_unparse(ctx->fs->super->s_uuid, uuid);
sprintf(db->tdb_fn, "%s/%s-dirinfo-XXXXXX", tdb_dir, uuid);
@@ -74,7 +74,7 @@ static void setup_tdb(e2fsck_t ctx, ext2_ino_t num_dirs)
umask(save_umask);
if (fd < 0) {
db->tdb = NULL;
- return;
+ goto tdb_fn_error;
}

if (num_dirs < 99991)
@@ -83,6 +83,15 @@ static void setup_tdb(e2fsck_t ctx, ext2_ino_t num_dirs)
db->tdb = tdb_open(db->tdb_fn, num_dirs, TDB_NOLOCK | TDB_NOSYNC,
O_RDWR | O_CREAT | O_TRUNC, 0600);
close(fd);
+
+ return;
+
+tdb_fn_error:
+ ext2fs_free_mem(&db->tdb_fn);
+tdb_dir_error:
+ if (tdb_dir) {
+ free(tdb_dir);
+ }
}
#endif

--
2.27.0



2023-01-18 05:39:59

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH v3] setup_tdb : fix memory leak

On Tue, Jan 04, 2022 at 08:09:16PM +0800, zhanchengbin wrote:
> In setup_tdb(), need free tdb_dir and db->tdb_fn before return,
> otherwise it will cause memory leak.

This patch is not correct. tdb_dir is returned by
profile_get_string(), and it does *not* need to be freed. In fact, if
you had tested this using valgrind or AddressSanitizer, it would have
failed because tdb_dir is in the *middle* of an allocated block[1],
and this would have corrupted the heap data structures leading to all
sorts of potential problems.

[1] And that allocated block is freed by profile_release()

In addition, tdb->tdb_fn will be freed by e2fsck_free_dir_info(), and
so freeing it on the error path in setup_tdb() will result in a
double-free when e2fsck_free_dir_info() gets called.

I'm guessing you didn't actually test this patch with the code paths
in question --- that is, by triggering an error while using something
like ASan or valgrid? Note that corrupting the heap may lead to an
exploitable security bug, so if you have applied this patch in your
production version of e2fsprogs, I suggest that you revert it.

Cheers,

- Ted