Bug 2244992

Summary: glibc: Improve compatibility of ELF destructor ordering
Product: [Fedora] Fedora Reporter: Florian Weimer <fweimer>
Component: glibcAssignee: Florian Weimer <fweimer>
Status: CLOSED ERRATA QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: medium Docs Contact:
Priority: unspecified    
Version: 37CC: alexey.radkov, arjun, codonell, dj, fberat, fweimer, jlaw, mcermak, mcoufal, mfabian, pfrankli, sipoyare, skolosov
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
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:
Story Points: ---
Clone Of: Environment:
Last Closed: 2023-11-15 02:00:37 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
glibc-vim-libcall-failure none

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.