[DTrace-devel] [PATCH 6/8] btf: fix memory leaks
Nick Alcock
nick.alcock at oracle.com
Thu Apr 4 19:58:36 UTC 2024
On 3 Apr 2024, Kris Van Hees via DTrace-devel said:
> Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
A bit more to do :(
> ---
> libdtrace/dt_btf.c | 21 ++++++++++++++++-----
> libdtrace/dt_btf.h | 1 +
> libdtrace/dt_module.c | 2 +-
> libdtrace/dt_open.c | 3 +++
> 4 files changed, 21 insertions(+), 6 deletions(-)
>
> diff --git a/libdtrace/dt_btf.c b/libdtrace/dt_btf.c
> index 3f713632..020c7877 100644
> --- a/libdtrace/dt_btf.c
> +++ b/libdtrace/dt_btf.c
> @@ -240,7 +240,7 @@ dt_btf_load(dtrace_hdl_t *dtp, const char *fn)
>
> fp = fopen(fn, "rb");
> if (fp == NULL)
> - return dt_btf_set_load_errno(dtp, errno);
> + goto err;
>
> /* First see whether this might be a file with raw BTF data. */
> if (fread(&hdr, 1, sizeof(hdr), fp) < sizeof(hdr))
> @@ -317,12 +317,12 @@ elf_fail_no_end:
> dt_btf_error(dtp, 0, "BTF: %s", elf_errmsg(err));
> fclose(fp);
>
> - return NULL;
> -
> fail:
> dt_free(dtp, data);
> +
> +err:
> + dt_free(dtp, btf);
This should be a dt_btf_destroy(), since you might have allocated
btf->data by the time you enter elf_fail.
There's another leak above:
data = dt_alloc(dtp, st.st_size);
if (data == NULL)
goto fail;
if (fread(data, 1, st.st_size, fp) < st.st_size)
goto fail;
That second fail has allocated 'data' but not yet assigned it to
btf->data, so even if you *do* use dt_btf_destroy() where I flagged, it
wouldn't free it...
> dt_btf_set_errno(dtp, err ? err : errno);
> - fclose(fp);
... this looks like you've turned a leak of btf into an fd leak of fp by
everything going down the fail path (all of which are entered before the
fclose() of fp on the non-fail paths above).
In summary, error paths are evil!
> @@ -752,7 +763,7 @@ dt_btf_load_module(dtrace_hdl_t *dtp, dt_module_t *dmp)
> snprintf(fn, sizeof(fn), "/sys/kernel/btf/%s", dmp->dm_name);
> btf = dt_btf_load_file(dtp, fn);
>
> - if (btf && strcmp(dmp->dm_name, "vmlinux") == 0)
> + if (btf && !dtp->dt_shared_btf && strcmp(dmp->dm_name, "vmlinux") == 0)
> dtp->dt_shared_btf = btf;
Is there some danger that dt_btf_load_module() wil be called on vmlinux
more than once? That's the only situation in which this change would
constitute a leak fix.
> + if (dtp->dt_shared_btf != NULL)
> + dt_btf_destroy(dtp, dtp->dt_shared_btf);
Unnecessary != NULL check. (It's unnecessary in the CTF case below, too.)
--
NULL && (void)
More information about the DTrace-devel
mailing list