tpm2-tss icon indicating copy to clipboard operation
tpm2-tss copied to clipboard

Memory leak in error path of Esys_Initialize

Open polarina opened this issue 9 months ago • 3 comments

Esys_Initialize initializes the TCTI:

https://github.com/tpm2-software/tpm2-tss/blob/9f336a5064a0295608ca0e7a4d70c4db18664a37/src/tss2-esys/esys_context.c#L71-L75

The function Tss2_TctiLdr_Initialize (via Tss2_TctiLdr_Initialize_Ex) allocates memory that is not implicitly freed on failure:

https://github.com/tpm2-software/tpm2-tss/blob/9f336a5064a0295608ca0e7a4d70c4db18664a37/src/tss2-tcti/tctildr.c#L521-L528

When Tss2_TctiLdr_Initialize returns after a failure, the cleanup_return in Esys_Initialize is then executed:

https://github.com/tpm2-software/tpm2-tss/blob/9f336a5064a0295608ca0e7a4d70c4db18664a37/src/tss2-esys/esys_context.c#L95-L98

However, after the execution of Tss2_Tcti_Finalize there is a missing call to free unlike what is done in the error path of Tss2_TctiLdr_Initialize_Ex:

https://github.com/tpm2-software/tpm2-tss/blob/9f336a5064a0295608ca0e7a4d70c4db18664a37/src/tss2-tcti/tctildr.c#L530-L535

polarina avatar May 16 '24 15:05 polarina

@polarina In the cleanup_return part of Esys_Initialize``Tss2_TctiLdr_Finalize is called. This function calls tctildr_finalize where the tcti context is freed. So there is no leak, is there?

JuergenReppSIT avatar May 17 '24 13:05 JuergenReppSIT

@polarina In the cleanup_return part of Esys_InitializeTss2_TctiLdr_Finalize `` is called. This function calls tctildr_finalize where the tcti context is freed. So there is no leak, is there?

There is. There is no call to free on tctiContext.

Here is a reproducer:

#include <tss2/tss2_esys.h>

int main(void) {
	ESYS_CONTEXT *ctx = NULL;
	TSS2_RC rc = Esys_Initialize(&ctx, NULL, NULL);

	if (rc) {
		return 1;
	}

	Esys_Finalize(&ctx);
	return 0;
}

Compile with gcc esys-leak.c -l tss2-esys -o esys-leak and run via Valgrind, valgrind --leak-check=full -s ./esys-leak, as an unprivileged user who does not have access to the TPM:

==1309605== 
==1309605== HEAP SUMMARY:
==1309605==     in use at exit: 96 bytes in 1 blocks
==1309605==   total heap usage: 103 allocs, 102 frees, 56,932 bytes allocated
==1309605== 
==1309605== 96 bytes in 1 blocks are definitely lost in loss record 1 of 1
==1309605==    at 0x484A0FC: calloc (vg_replace_malloc.c:1675)
==1309605==    by 0x48E810E: UnknownInlinedFun (tctildr.c:520)
==1309605==    by 0x48E810E: UnknownInlinedFun (tctildr.c:551)
==1309605==    by 0x48E810E: Esys_Initialize (esys_context.c:70)
==1309605==    by 0x40115B: main (in /home/gabriel/rusl/esys-leak)
==1309605== 
==1309605== LEAK SUMMARY:
==1309605==    definitely lost: 96 bytes in 1 blocks
==1309605==    indirectly lost: 0 bytes in 0 blocks
==1309605==      possibly lost: 0 bytes in 0 blocks
==1309605==    still reachable: 0 bytes in 0 blocks
==1309605==         suppressed: 0 bytes in 0 blocks
==1309605== 
==1309605== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

LeakSanitizer also picks up the leak:

=================================================================
==1309536==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 96 byte(s) in 1 object(s) allocated from:
    #0 0x7f820e0f6270 in calloc (/lib64/libasan.so.8+0xf6270) (BuildId: 6ac482fdae6aad7cf603c8e6ab3042fb9d4725af)
    #1 0x7f820e89310e in Esys_Initialize (/lib64/libtss2-esys.so.0+0x6810e) (BuildId: 901c827f0bb06673b2cdd265db2e59474ed57294)
    #2 0x401222 in main (/home/gabriel/rusl/esys-leak+0x401222) (BuildId: b88db0d10e252a64478a432c120c6c5f8c9b8d16)
    #3 0x7f820de3d087 in __libc_start_call_main (/lib64/libc.so.6+0x2a087) (BuildId: b098f1c75a76548bb230d8f551eae07a2aeccf06)
    #4 0x7f820de3d14a in __libc_start_main_alias_2 (/lib64/libc.so.6+0x2a14a) (BuildId: b098f1c75a76548bb230d8f551eae07a2aeccf06)
    #5 0x4010b4 in _start (/home/gabriel/rusl/esys-leak+0x4010b4) (BuildId: b88db0d10e252a64478a432c120c6c5f8c9b8d16)

SUMMARY: AddressSanitizer: 96 byte(s) leaked in 1 allocation(s).

polarina avatar May 17 '24 14:05 polarina

@polarina Thank you for the example. I will create a PR.

JuergenReppSIT avatar May 18 '24 18:05 JuergenReppSIT