Bug 2244992 - glibc: Improve compatibility of ELF destructor ordering
Summary: glibc: Improve compatibility of ELF destructor ordering
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Fedora
Classification: Fedora
Component: glibc
Version: 37
Hardware: All
OS: Linux
unspecified
medium
Target Milestone: ---
Assignee: Florian Weimer
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2023-10-19 07:02 UTC by Florian Weimer
Modified: 2023-11-29 01:39 UTC (History)
13 users (show)

Fixed In Version: glibc-2.38.9000-19.fc40 glibc-2.36-18.fc37 glibc-2.37-14.fc38 glibc-2.38-11.fc39
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2023-11-15 02:00:37 UTC
Type: ---
Embargoed:


Attachments (Terms of Use)
glibc-vim-libcall-failure (54.08 KB, image/png)
2023-10-24 16:05 UTC, Alexey Radkov
no flags Details


Links
System ID Private Priority Status Summary Last Updated
Red Hat Bugzilla 2239304 0 unspecified CLOSED glibc: Revert change to run ELF destructor in reverse constructor order 2023-11-15 02:02:27 UTC
Red Hat Bugzilla 2246048 0 unspecified CLOSED glibc: MALLOC_PERTURB_ causes ld.so to fail dlclose 2023-11-29 01:39:27 UTC
Sourceware 30981 0 P2 NEW dlclose does not properly implement force-first handling 2023-10-19 07:05:02 UTC

Internal Links: 2239304 2246048

Description Florian Weimer 2023-10-19 07:02:34 UTC
In some cases, dlclose does not call the destructor of the shared object it is invoked on first, which causes application compatibility issues.

This is another attempt at fixing the issue that the reverse ELF constructor ordering change tried to address (the approach that lead to bug 2239304).

Reproducible: Always

Comment 1 Fedora Update System 2023-10-20 09:49:07 UTC
FEDORA-2023-cec30b1297 has been submitted as an update to Fedora 39. https://bodhi.fedoraproject.org/updates/FEDORA-2023-cec30b1297

Comment 2 Fedora Update System 2023-10-20 09:55:16 UTC
FEDORA-2023-7dfa1f6429 has been submitted as an update to Fedora 38. https://bodhi.fedoraproject.org/updates/FEDORA-2023-7dfa1f6429

Comment 3 Fedora Update System 2023-10-20 09:55:49 UTC
FEDORA-2023-eb57cdaf88 has been submitted as an update to Fedora 37. https://bodhi.fedoraproject.org/updates/FEDORA-2023-eb57cdaf88

Comment 4 Fedora Update System 2023-10-21 02:27:27 UTC
FEDORA-2023-cec30b1297 has been pushed to the Fedora 39 testing repository.
Soon you'll be able to install the update with the following command:
`sudo dnf upgrade --enablerepo=updates-testing --refresh --advisory=FEDORA-2023-cec30b1297`
You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2023-cec30b1297

See also https://fedoraproject.org/wiki/QA:Updates_Testing for more information on how to test updates.

Comment 5 Fedora Update System 2023-10-21 02:39:50 UTC
FEDORA-2023-7dfa1f6429 has been pushed to the Fedora 38 testing repository.
Soon you'll be able to install the update with the following command:
`sudo dnf upgrade --enablerepo=updates-testing --refresh --advisory=FEDORA-2023-7dfa1f6429`
You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2023-7dfa1f6429

See also https://fedoraproject.org/wiki/QA:Updates_Testing for more information on how to test updates.

Comment 6 Fedora Update System 2023-10-21 02:40:33 UTC
FEDORA-2023-eb57cdaf88 has been pushed to the Fedora 37 testing repository.
Soon you'll be able to install the update with the following command:
`sudo dnf upgrade --enablerepo=updates-testing --refresh --advisory=FEDORA-2023-eb57cdaf88`
You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2023-eb57cdaf88

See also https://fedoraproject.org/wiki/QA:Updates_Testing for more information on how to test updates.

Comment 7 Fedora Update System 2023-10-23 02:59:00 UTC
FEDORA-2023-7dfa1f6429 has been pushed to the Fedora 38 stable repository.
If problem still persists, please make note of it in this bug report.

Comment 8 Alexey Radkov 2023-10-24 13:54:52 UTC
It seems that after this fix libcall functionality used in vim-xkbswitch plugin began to cause crashes in both vim and neovim.

Vim backtrace (a part of):

#0  dfs_traversal (rpo=rpo@entry=0x7fffe5376c80, map=0x564b0744f6b0, do_reldeps=do_reldeps@entry=0x7fffe5376c7f) at dl-sort-maps.c:165
#1  0x00007f853188c4db in dfs_traversal (do_reldeps=<optimized out>, map=<optimized out>, rpo=<optimized out>) at dl-sort-maps.c:178
#2  dfs_traversal (rpo=rpo@entry=0x7fffe5376c80, map=0x564b0743f530, do_reldeps=do_reldeps@entry=0x7fffe5376c7f) at dl-sort-maps.c:157
#3  0x00007f853188c52c in dfs_traversal (do_reldeps=<optimized out>, map=<optimized out>, rpo=<optimized out>) at dl-sort-maps.c:169
#4  dfs_traversal (rpo=rpo@entry=0x7fffe5376c80, map=0x564b0744dcb0, do_reldeps=do_reldeps@entry=0x7fffe5376c7f) at dl-sort-maps.c:172
#5  0x00007f853188c8f4 in dfs_traversal (do_reldeps=<optimized out>, map=<optimized out>, rpo=0x7fffe5376c80) at dl-sort-maps.c:145
#6  _dl_sort_maps_dfs (for_fini=true, force_first=true, nmaps=<optimized out>, maps=0x7fffe5376cd0) at dl-sort-maps.c:228
#7  _dl_sort_maps (maps=maps@entry=0x7fffe5376cd0, nmaps=nmaps@entry=17, force_first=true, for_fini=for_fini@entry=true) at dl-sort-maps.c:314
#8  0x00007f853187cb07 in _dl_close_worker (map=<optimized out>, map@entry=0x564b0743f530, force=force@entry=false) at dl-close.c:240
#9  0x00007f853187d67b in _dl_close (_map=0x564b0743f530) at dl-close.c:791
#10 0x00007f853187c523 in __GI__dl_catch_exception (exception=exception@entry=0x7fffe5376f60, operate=0x7f853187d640 <_dl_close>, args=0x564b0743f530) at dl-catch.c:237
#11 0x00007f853187c679 in _dl_catch_error (objname=0x7fffe5376fc8, errstring=0x7fffe5376fd0, mallocedp=0x7fffe5376fc7, operate=<optimized out>, args=<optimized out>) at dl-catch.c:256
#12 0x00007f85315581f3 in _dlerror_run (operate=<optimized out>, args=<optimized out>) at dlerror.c:138
#13 0x00007f8531557f26 in __dlclose (handle=<optimized out>) at dlclose.c:31
#14 0x0000564b05256dc8 in mch_libcall (libname=<optimized out>, funcname=0x564b07516470 "Xkb_Switch_getXkbLayout", argstring=0x564b06c4e890 "", argint=113567888, 
    string_result=0x7fffe5377e28, number_result=0x7fffe5377094) at /usr/src/debug/vim-9.0.2048-1.fc38.x86_64/src/os_unix.c:7867
#15 0x0000564b051662ab in libcall_common (argvars=0x7fffe5377550, rettv=0x7fffe5377e20, type=7) at /usr/src/debug/vim-9.0.2048-1.fc38.x86_64/src/evalfunc.c:7585

Neovim backtrace (a part of):

#0  dfs_traversal (rpo=rpo@entry=0x7ffe2a979a70, map=0x5615455f3060, do_reldeps=do_reldeps@entry=0x7ffe2a979a6f) at dl-sort-maps.c:152
#1  0x00007fb13faf54db in dfs_traversal (do_reldeps=<optimized out>, map=<optimized out>, rpo=<optimized out>) at dl-sort-maps.c:178
#2  dfs_traversal (rpo=rpo@entry=0x7ffe2a979a70, map=0x5615455eeee0, do_reldeps=do_reldeps@entry=0x7ffe2a979a6f) at dl-sort-maps.c:157
#3  0x00007fb13faf552c in dfs_traversal (do_reldeps=<optimized out>, map=<optimized out>, rpo=<optimized out>) at dl-sort-maps.c:169
#4  dfs_traversal (rpo=rpo@entry=0x7ffe2a979a70, map=0x5615455f2b80, do_reldeps=do_reldeps@entry=0x7ffe2a979a6f) at dl-sort-maps.c:172
#5  0x00007fb13faf58f4 in dfs_traversal (do_reldeps=<optimized out>, map=<optimized out>, rpo=0x7ffe2a979a70) at dl-sort-maps.c:145
#6  _dl_sort_maps_dfs (for_fini=true, force_first=true, nmaps=<optimized out>, maps=0x7ffe2a979ac0) at dl-sort-maps.c:228
#7  _dl_sort_maps (maps=maps@entry=0x7ffe2a979ac0, nmaps=nmaps@entry=18, force_first=true, for_fini=for_fini@entry=true) at dl-sort-maps.c:314
#8  0x00007fb13fae5b07 in _dl_close_worker (map=<optimized out>, map@entry=0x5615455eeee0, force=force@entry=false) at dl-close.c:240
#9  0x00007fb13fae667b in _dl_close (_map=0x5615455eeee0) at dl-close.c:791
#10 0x00007fb13fae5523 in __GI__dl_catch_exception (exception=exception@entry=0x7ffe2a979d50, operate=0x7fb13fae6640 <_dl_close>, args=0x5615455eeee0) at dl-catch.c:237
#11 0x00007fb13fae5679 in _dl_catch_error (objname=0x7ffe2a979db8, errstring=0x7ffe2a979dc0, mallocedp=0x7ffe2a979db7, operate=<optimized out>, args=<optimized out>) at dl-catch.c:256
#12 0x00007fb13f7281f3 in _dlerror_run (operate=<optimized out>, args=<optimized out>) at dlerror.c:138
#13 0x00007fb13f727f26 in __dlclose (handle=<optimized out>) at dlclose.c:31
#14 0x00007fb13f894aa3 in uv_dlclose (lib=lib@entry=0x7ffe2a979e70) at src/unix/dl.c:47
#15 0x0000561543646f11 in os_libcall (libname=<optimized out>, funcname=0x5615454f9ba0 "Xkb_Switch_getXkbLayout", argv=0x561545326940 "", argi=1160931648, str_out=0x7ffe2a97a868, 
    int_out=0x7ffe2a979ed4) at /usr/src/debug/neovim-0.9.2-1.fc38.x86_64/src/nvim/os/dl.c:86
#16 0x00005615435588d4 in libcall_common (argvars=0x7ffe2a97a1b0, rettv=0x7ffe2a97a860, out_type=out_type@entry=2) at /usr/src/debug/neovim-0.9.2-1.fc38.x86_64/src/nvim/eval/funcs.c:4469

They look similar and crash ar dlclose().

Comment 9 Florian Weimer 2023-10-24 15:14:56 UTC
I agree that this is suspicious.

Do you have instructions how to reproduce this? I can stare at the code for a while, hoping to see the bug, but so far, nothing.

Comment 10 Alexey Radkov 2023-10-24 16:04:32 UTC
Here is very simple test. Run vim (or nvim). Print

:echo libcall("/usr/lib64/libabrt.so.0", "test", "test")

(I took any existing library, in this case libabrt.so.0, and called some inexistent function (test) with argument "test".


Before the fix.

vim says:

dlerror = "/usr/lib64/libabrt.so.0: undefined symbol: test"
E364: Library call failed for "test()"

This is ok. Then press <Enter> and vim still works.


After the fix.

vim shuts down, the following message appears on the screen (I'll attach it because the screen is broken after vim's exit and I cannot select the text).

Comment 11 Alexey Radkov 2023-10-24 16:05:54 UTC
Created attachment 1995291 [details]
glibc-vim-libcall-failure

Comment 12 Alexey Radkov 2023-10-24 16:09:45 UTC
There image says that symbol "test" is undefined (like in the good case brfore the fix) and right after this the vim shuts down breaking the terminal input. I forgot to switch to LANG=C in this case so there were some Russian in messages.

Comment 13 Florian Weimer 2023-10-24 21:32:06 UTC
(In reply to Alexey Radkov from comment #10)
> Here is very simple test. Run vim (or nvim). Print
> 
> :echo libcall("/usr/lib64/libabrt.so.0", "test", "test")
> 
> (I took any existing library, in this case libabrt.so.0, and called some
> inexistent function (test) with argument "test".

That would be a really helpful reproducer, but it doesn't reproduce for me with:

abrt-libs-2.17.1-1.fc38.x86_64
glibc-2.37-12.fc38.x86_64
vim-enhanced-9.0.2048-1.fc38.x86_64

And the default vim configuration, after install vim-enhanced and abrt-libs into an (updated) Fedora 38 container image.

Comment 14 Alexey Radkov 2023-10-25 07:28:22 UTC
@fweimer you're right, clean vim (without plugins) works fine. Here is a batch one-liner:

$ LANG=C /usr/bin/vim -u NONE -Nesn -T dumb -c ':verbose echo libcall("/usr/lib64/libabrt.so.0", "test", "test")' -c ':verbose echo "Ok\n"' -c ':q!'
Error detected while processing command line:
dlerror = "/usr/lib64/libabrt.so.0: undefined symbol: test"
E364: Library call failed for "test()"
Ok

It seems that the problem in the vim-xkbswitch library. The vim help says about libcall

		and must return a character pointer or NULL.  The character
		pointer returned must point to memory that will remain valid
		after the function has returned (e.g. in static data in the
		DLL).  If it points to allocated memory, that memory will
		leak away.  Using a static buffer in the function should work,
		it's then freed when the DLL is unloaded.

The vim-xkbswitch library is written in C++, and the result is stored in an anonymous global namespace which is probably does not meet the *memory that will remain valid after the function has returned (e.g. in static data in the DLL)* requirement. I'll check this. Anyway, this implementation worked for years before this glibc fix.

Update. Ah, I see that what stored in the global namespace is a vector of strings whose elements cannot be stored in a static memory. This could be the cause of the problem.

Comment 15 Florian Weimer 2023-10-25 08:59:26 UTC
(In reply to Alexey Radkov from comment #14)
> @fweimer you're right, clean vim (without plugins) works fine.
> Here is a batch one-liner:
> 
> $ LANG=C /usr/bin/vim -u NONE -Nesn -T dumb -c ':verbose echo
> libcall("/usr/lib64/libabrt.so.0", "test", "test")' -c ':verbose echo
> "Ok\n"' -c ':q!'
> Error detected while processing command line:
> dlerror = "/usr/lib64/libabrt.so.0: undefined symbol: test"
> E364: Library call failed for "test()"
> Ok
> 
> It seems that the problem in the vim-xkbswitch library. The vim help says
> about libcall
> 
> 		and must return a character pointer or NULL.  The character
> 		pointer returned must point to memory that will remain valid
> 		after the function has returned (e.g. in static data in the
> 		DLL).  If it points to allocated memory, that memory will
> 		leak away.  Using a static buffer in the function should work,
> 		it's then freed when the DLL is unloaded.
> 
> The vim-xkbswitch library is written in C++, and the result is stored in an
> anonymous global namespace which is probably does not meet the *memory that
> will remain valid after the function has returned (e.g. in static data in
> the DLL)* requirement. I'll check this. Anyway, this implementation worked
> for years before this glibc fix.
> 
> Update. Ah, I see that what stored in the global namespace is a vector of
> strings whose elements cannot be stored in a static memory. This could be
> the cause of the problem.

Still this shouldn't really cause a crash with the backtrace you observed. A crash in application code is possible under these circumstances, but ld.so functions such as dfs_traversal would not show up in the stack trace.

It's likely that there is some glibc bug here. We have another report about a regression in bug 2246048, too.

Comment 16 Alexey Radkov 2023-10-26 09:36:53 UTC
Interestingly, a library with similar functionality written in C, being used instead of the C++ library works well.

$ ldd /usr/local/lib64/libg3kbswitch.so
	linux-vdso.so.1 (0x00007fff3cb4c000)
	libgio-2.0.so.0 => /lib64/libgio-2.0.so.0 (0x00007fa4009cc000)
	libgobject-2.0.so.0 => /lib64/libgobject-2.0.so.0 (0x00007fa40096c000)
	libglib-2.0.so.0 => /lib64/libglib-2.0.so.0 (0x00007fa400823000)
	libc.so.6 => /lib64/libc.so.6 (0x00007fa400645000)
	libgmodule-2.0.so.0 => /lib64/libgmodule-2.0.so.0 (0x00007fa40063e000)
	libz.so.1 => /lib64/libz.so.1 (0x00007fa400624000)
	libmount.so.1 => /lib64/libmount.so.1 (0x00007fa4005dc000)
	libselinux.so.1 => /lib64/libselinux.so.1 (0x00007fa4005af000)
	libffi.so.8 => /lib64/libffi.so.8 (0x00007fa4005a3000)
	libpcre2-8.so.0 => /lib64/libpcre2-8.so.0 (0x00007fa400509000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fa400bc5000)
	libblkid.so.1 => /lib64/libblkid.so.1 (0x00007fa4004d1000)

works,

$ ldd /usr/local/lib/libxkbswitch.so
	linux-vdso.so.1 (0x00007ffe8e99f000)
	libX11.so.6 => /lib64/libX11.so.6 (0x00007f3a5b6b0000)
	libxkbfile.so.1 => /lib64/libxkbfile.so.1 (0x00007f3a5b688000)
	libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f3a5b400000)
	libm.so.6 => /lib64/libm.so.6 (0x00007f3a5b31f000)
	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f3a5b664000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f3a5b141000)
	libxcb.so.1 => /lib64/libxcb.so.1 (0x00007f3a5b116000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f3a5b827000)
	libXau.so.6 => /lib64/libXau.so.6 (0x00007f3a5b65c000)

crashes vim.

The code of the libraries is open: https://github.com/lyokha/g3kb-switch/blob/master/switch-api.c (good), https://github.com/grwlf/xkb-switch/blob/master/src/XKbSwitchApi.cpp (bad). I once removed all in the global namespace of the bad library and switched to return a string literal from Xkb_Switch_getXkbLayout() but it didn't help.

Comment 17 Fedora Update System 2023-10-31 02:21:10 UTC
FEDORA-2023-3b9da12381 has been pushed to the Fedora 37 testing repository.
Soon you'll be able to install the update with the following command:
`sudo dnf upgrade --enablerepo=updates-testing --refresh --advisory=FEDORA-2023-3b9da12381`
You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2023-3b9da12381

See also https://fedoraproject.org/wiki/QA:Updates_Testing for more information on how to test updates.

Comment 18 Fedora Update System 2023-11-03 18:42:54 UTC
FEDORA-2023-cec30b1297 has been pushed to the Fedora 39 stable repository.
If problem still persists, please make note of it in this bug report.

Comment 19 Fedora Update System 2023-11-15 02:00:37 UTC
FEDORA-2023-3b9da12381 has been pushed to the Fedora 37 stable repository.
If problem still persists, please make note of it in this bug report.

Comment 20 Fedora Update System 2023-11-20 12:22:27 UTC
FEDORA-2023-13d599718b has been submitted as an update to Fedora 39. https://bodhi.fedoraproject.org/updates/FEDORA-2023-13d599718b

Comment 21 Fedora Update System 2023-11-20 12:23:09 UTC
FEDORA-2023-b5c7c2ff8b has been submitted as an update to Fedora 38. https://bodhi.fedoraproject.org/updates/FEDORA-2023-b5c7c2ff8b

Comment 22 Fedora Update System 2023-11-20 13:09:39 UTC
FEDORA-2023-04796d3939 has been submitted as an update to Fedora 37. https://bodhi.fedoraproject.org/updates/FEDORA-2023-04796d3939

Comment 23 Fedora Update System 2023-11-21 01:30:44 UTC
FEDORA-2023-b5c7c2ff8b has been pushed to the Fedora 38 testing repository.
Soon you'll be able to install the update with the following command:
`sudo dnf upgrade --enablerepo=updates-testing --refresh --advisory=FEDORA-2023-b5c7c2ff8b`
You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2023-b5c7c2ff8b

See also https://fedoraproject.org/wiki/QA:Updates_Testing for more information on how to test updates.

Comment 24 Fedora Update System 2023-11-21 02:16:40 UTC
FEDORA-2023-04796d3939 has been pushed to the Fedora 37 testing repository.
Soon you'll be able to install the update with the following command:
`sudo dnf upgrade --enablerepo=updates-testing --refresh --advisory=FEDORA-2023-04796d3939`
You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2023-04796d3939

See also https://fedoraproject.org/wiki/QA:Updates_Testing for more information on how to test updates.

Comment 25 Fedora Update System 2023-11-21 02:31:00 UTC
FEDORA-2023-13d599718b has been pushed to the Fedora 39 testing repository.
Soon you'll be able to install the update with the following command:
`sudo dnf upgrade --enablerepo=updates-testing --refresh --advisory=FEDORA-2023-13d599718b`
You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2023-13d599718b

See also https://fedoraproject.org/wiki/QA:Updates_Testing for more information on how to test updates.

Comment 26 Fedora Update System 2023-11-23 01:24:20 UTC
FEDORA-2023-13d599718b has been pushed to the Fedora 39 stable repository.
If problem still persists, please make note of it in this bug report.

Comment 27 Fedora Update System 2023-11-27 02:31:24 UTC
FEDORA-2023-b5c7c2ff8b has been pushed to the Fedora 38 stable repository.
If problem still persists, please make note of it in this bug report.

Comment 28 Fedora Update System 2023-11-29 01:39:24 UTC
FEDORA-2023-04796d3939 has been pushed to the Fedora 37 stable repository.
If problem still persists, please make note of it in this bug report.


Note You need to log in before you can comment on or make changes to this bug.