Bug 29516 - Memory leak when dlclose is called by library destructor
Summary: Memory leak when dlclose is called by library destructor
Status: UNCONFIRMED
Alias: None
Product: glibc
Classification: Unclassified
Component: dynamic-link (show other bugs)
Version: 2.35
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-08-23 20:31 UTC by Videau, Brice
Modified: 2023-09-11 07:27 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Videau, Brice 2022-08-23 20:31:17 UTC
Hello,

I was experimenting with dynamic libraries that use other dynamic libraries as plugins, through dlopen and dlclose, and noticed that when the dlcose is called in a function tagged with the __attribute__((destructor)), valgrind reported unreleased memory. If the cleanup function is called directly by the program, the leak disappears. I confirmed the behavior using strace, that displays an additional unmap when the cleanup is done explicitly.

I developed a reproducer here:
https://github.com/Kerilk/layering-research/tree/reproducer

and it can be ran on a Linux platform that has git, gcc, and valgrind installed.

git clone -b reproducer git@github.com:Kerilk/layering-research.git
cd layering-research/
./build.sh
./run.sh

Should be enough to reproduce. The run.sh script invokes the reproducer twice. The first run is for the case where the library destructor calls dlclose, while the second run is for the case where the dlclose is called explicitly by the application. The results on my platform are given in the reproducer README.md.

Running the reproducer manually with strace yields:

$ LD_LIBRARY_PATH=`pwd` strace ./test 2>&1 | grep unmap
munmap(0x7f2aa0ffc000, 128371)          = 0

when dlclose is called from the destructor.

$ FIX=1 LD_LIBRARY_PATH=`pwd` strace ./test 2>&1 | grep unmap
munmap(0x7f42f0828000, 128371)          = 0
munmap(0x7f42f0843000, 16432)           = 0

when dlclose is called explicitly.

I also cloned and built the current glibc tree (2022-08-21) and witnessed the same behavior.
I looked through the dlclose code, as well as opened bug reports, and couldn't determine if it was intended behavior.

Sorry if this is known and expected.

Best,
Brice
Comment 1 Videau, Brice 2022-08-23 20:35:10 UTC
I realize I forgot to mention that I tested this behavior on several x86-64 Linux distributions and platforms with glibc ranging from 2.30 to 2.35 and got the same results.
Comment 2 Andreas Schwab 2023-03-08 16:48:51 UTC
elf/dl-fini.c:_dl_fini

		/* Bump l_direct_opencount of all objects so that they
		   are not dlclose()ed from underneath us.  */
		++l->l_direct_opencount;
Comment 3 Florian Weimer 2023-09-11 07:27:38 UTC
This issue should go away with RELRO link maps because valgrind does not track allocations in the protected memory allocator.