On Thu, Feb 23, 2023 at 01:03:50AM +0100, Vincent Danjean wrote: > After doing a partial upgrade of my system (i.e. only libvirt-daemon > with its required dependencies), libvirtd refused to start. > In systemd journal, I can see: > > févr. 23 00:53:32 eyak libvirtd[3010536]: internal error: Failed to load > module > '/usr/lib/x86_64-linux-gnu/libvirt/connection-driver/libvirt_driver_lxc.so': > /usr/lib/x86_64-linux-gnu/libvirt/connection-driver/libvirt_driver_lxc.so: > undefined symbol: fuse_new_31, version FUSE_3.1 > > Upgrading libfuse3-3 from 3.12.0-1 to 3.14.0-2 fixed the problem. > libvirt-daemon-driver-lxc should bump its dependency on libfuse3-3. > For now, there is: > Depends: [...] libfuse3-3 (>= 3.2.3) [...] > > If this dependency is automaticcaly generated, then it probably > means there is a bug in the libfuse3-3 package (its shlibs file)
Hi Vincent, thanks for taking the time to report this issue, and sorry it took me a few weeks to get back to you. After successfully reproducing it by downgrading my machine to libvirt 9.0.0-1 and fuse3 3.12.0-1 builds obtained from snapshot.d.o, I have spent some time trying to figure out the root cause. tl;dr it's indeed an issue with fuse3's symbols file. Comparing the exported symbols for libfuse3.so.3, we can see that 3.12.0-1 contains 0000000000013af0 g DF .text 0000000000000111 FUSE_3.1 fuse_new_30 0000000000013af0 g DF .text 0000000000000111 (FUSE_3.0) fuse_new 00000000000134f0 g DF .text 00000000000005f8 FUSE_3.1 fuse_new and 3.14.0-2 contains 0000000000014a70 g DF .text 0000000000000111 FUSE_3.1 fuse_new_30 0000000000014470 g DF .text 00000000000005f8 FUSE_3.1 fuse_new_31 0000000000014a70 g DF .text 0000000000000111 (FUSE_3.0) fuse_new 0000000000014470 g DF .text 00000000000005f8 FUSE_3.1 fuse_new Notice how fuse_new_31, the function that libvirt_driver_lxc.so references, only shows up in the latter. Looking at the build log for libvirt 9.0.0-1 https://buildd.debian.org/status/fetch.php?pkg=libvirt&arch=amd64&ver=9.0.0-1&stamp=1674930232&raw=0 we can see that it was built against fuse3 3.13.0-2. That version exports the same symbols as 3.14.0-2, so we can use them interchangeably for the purpose of this discussion. Now, there are some shenanigans in include/fuse.h from version 3.13.0 onwards that result in libvirt (which defines FUSE_USE_VERSION=31 in its source) referencing fuse_new_31@FUSE_3.1. If you look at older builds of libvirt, for example 8.10.0-3 (which was built against fuse3 3.12.0-2), you'll see that fuse_new@FUSE_3.1 is referenced instead. To be honest I haven't looked too hard at the logic there, but the outcome is self-apparent. Building against fuse3 3.13 results in picking up the new symbol, which 3.12 didn't have, and so libvirt will only work with fuse3 >= 3.13. This wouldn't be a problem per se: libraries introduce new symbols all the time, and once programs start referencing them it's expected that they won't work with older versions of the library. In this case, however, as you've noticed libvirt-daemon-driver-lxc contains an inaccurate dependency: it claims that it can work with fuse3 >= 3.2.3, while we've just demonstrated that it really needs fuse3 >= 3.13.0-1. Why is this happening? Comparing the upstream version scripts for fuse 3.12 and 3.13, we can see the following differences: --- 12/lib/fuse_versionscript 2022-09-08 12:02:45.000000000 +0200 +++ 13/lib/fuse_versionscript 2023-01-13 11:33:35.000000000 +0100 @@ -39,6 +39,7 @@ fuse_session_new; fuse_main_real; fuse_mount; + fuse_session_custom_io; fuse_session_mount; fuse_new; fuse_opt_insert_arg; @@ -139,6 +140,7 @@ fuse_lib_help; fuse_invalidate_path; fuse_new_30; + fuse_new_31; fuse_new; } FUSE_3.0; @@ -184,6 +186,7 @@ fuse_parse_cmdline; fuse_parse_cmdline_30; fuse_parse_cmdline_312; + fuse_lowlevel_notify_expire_entry; } FUSE_3.4; # Local Variables: In other words, upstream developers have retroactively added symbols (fuse_new_31) to existing symbol groups (FUSE_3.1). This was probably done with good intentions, as the name of the function clearly indicates that it was introduced in version 3.1 and the fact that it was missing from the symbol group was almost certainly a bug. However, addressing the issue the way they've done it also has the unintended consequence that you've experienced. I believe it should be possible to work around this in Debian by adding an entry like fuse_new_31@FUSE_3.1 3.13.0 to debian/libfuse3-3.symbols, but really this looks like an upstream bug in my opinion: even if the function was present in the source code all the way back in 3.1, it's only publicly exported starting with 3.13, and so exposing it as fuse_new_31@FUSE_3.13 would have been the correct way to go about it IMO. Either way, this is for the fuse3 maintainer and upstream to decide, and there's nothing libvirt can do. I'm going to reassing the bug accordingly. -- Andrea Bolognani <e...@kiyuko.org> Resistance is futile, you will be garbage collected.
signature.asc
Description: PGP signature