** Description changed:

+ [ Impact ]
+ 
+ The base-files preinst refuses to install or upgrade when one of the
+ multilib aliasing symlinks (/lib32, /libo32, /libx32) points at a
+ /usr/<dir> that no longer exists:
+ 
+ ```
+ The base-files package cannot be installed because
+ /lib32 is a dangling symbolic link.
+ ```
+ 
+ These symlinks are optional and are created/removed on demand by the
+ base-files postinst (via a file trigger on /usr/<dir>). They can be
+ left dangling, e.g. when the last package shipping files in /usr/lib32
+ is removed. Affected users cannot upgrade base-files, which breaks apt
+ upgrades and release upgrades in some reported cases leaving the
+ system unbootable (Comment #15)
+ 
+ The fix makes the preinst remove a dangling multilib aliasing symlink
+ instead of aborting. The postinst recreates it if /usr/<dir> appears
+ later. Dangling /bin, /lib, /sbin (and the rtld dir, e.g. /lib64 on
+ amd64) are still treated as fatal.
+ 
+ [ Test Plan ]
+ 
+ In a fresh resolute (resp. stonking) container or VM (amd64):
+ 
+ 1. Confirm the multilib dir is absent:
+ 
+ ```
+ $ ls -ld /usr/lib32 /usr/libo32 /usr/libx32 /lib32 /libo32 /libx32
+ ```
+ 
+ All should report "No such file or directory".
+ 
+ 2. Reproduce with the current version:
+ 
+ ```
+ $ sudo ln -s usr/lib32 /lib32
+ $ sudo ln -s usr/libo32 /libo32
+ $ sudo ln -s usr/libx32 /libx32
+ $ sudo apt install --reinstall base-files
+ ```
+ 
+ Expected: dpkg fails with
+ `/lib32 is a dangling symbolic link ... Cannot proceed with the upgrade`
+ 
+ The old preinst stops at the first problem it finds, so it reports
+ `/lib32` even though all three links are broken.
+ 
+ 3. Enable `-proposed` and upgrade:
+ 
+ ```
+ $ sudo apt install -t <series>-proposed base-files
+ ```
+ 
+ Expected:
+ ```
+ Removing dangling /lib32 symbolic link.
+ Removing dangling /libo32 symbolic link.
+ Removing dangling /libx32 symbolic link.
+ ```
+ 
+ is printed, the install succeeds, `dpkg -s base-files` shows the new
+ version as installed, and:
+ 
+ ```
+ $ ls -ld /lib32 /libo32 /libx32
+ ```
+ 
+ reports "No such file or directory" for all three.
+ 
+ 4. Regression check, valid symlink kept and trigger still works:
+ 
+ ```
+ $ sudo apt install libc6-i386
+ $ ls -ld /usr/lib32    # directory exists
+ $ readlink /lib32      # -> usr/lib32 (created by the base-files trigger)
+ $ sudo apt install --reinstall base-files
+ ```
+ 
+ Expected: the install succeeds, NO `Removing dangling` message is
+ printed.
+ 
+ ```
+ $ readlink /lib32      # still -> usr/lib32
+ $ sudo apt purge libc6-i386 && sudo apt autoremove --purge
+ $ ls -ld /usr/lib32 /lib32
+ ```
+ 
+ Expected: both report `No such file or directory`. The trigger removes
+ /lib32 once /usr/lib32 is gone, so the link is never left dangling.
+ 
+ [ Where problems could occur ]
+ 
+ The change only affects the preinst branch where /<dir> is a symlink
+ to usr/<dir> and /usr/<dir> does not exist, and only for the multilib
+ aliasing dirs (lib32, libo32, libx32 and, on archs whose rtld dir is
+ not /lib64, lib64). In that state the symlink resolves to nothing, so
+ removing it cannot break path lookups. If something did rely on the
+ symlink existing (not its target), it would no longer find it. The
+ postinst/trigger recreates it as soon as /usr/<dir> exists again.
+ 
+ A mistake in the directory list could make the preinst delete an
+ essential symlink such as /lib64. The list comes from the same
+ `USR_MERGE_MULTILIB` build variable already used by the postinst and
+ trigger, which excludes bin, lib, sbin and the rtld dir.
+ 
+ [ Other Info ]
+ 
+ The test plan is run on amd64 only. This is sufficient because the
+ preinst itself is architecture-independent shell code, and the only
+ per-arch difference is the directory list substituted for
+ `#USR_MERGE_MULTILIB#` at build time, which debian/rules derives from
+ the architecture's rtld dir:
+ 
+ - amd64, ppc64el: lib32 libo32 libx32
+ - arm64, armhf, riscv64, s390x, i386: lib32 lib64 libo32 libx32
+ 
+ The same list is already substituted into the postinst and used for
+ the file triggers, so it is not new per-arch logic introduced by this
+ SRU. The changes run same commands for every entry in the list (an
+ echo and an rm of /<dir>), so exercising them on amd64 for lib32,
+ libo32 and libx32 covers the code path that every architecture runs.
+ 
+ [ Original Description ]
+ 
+ 
  Check on the report
  
  ProblemType: Package
  DistroRelease: Ubuntu 24.04
  Package: base-files 13ubuntu10.2
  Uname: Linux 6.16.0-061600rc6-generic x86_64
  ApportVersion: 2.28.1-0ubuntu3.8
  Architecture: amd64
  CasperMD5CheckResult: pass
  Date: Fri Nov 14 12:51:22 2025
  ErrorMessage: new base-files package pre-installation script subprocess 
returned error exit status 1
  InstallationDate: Installed on 2023-08-09 (828 days ago)
  InstallationMedia: Ubuntu 22.04.1 LTS "Jammy Jellyfish" - Release amd64 
(20220809.1)
  Python3Details: /usr/bin/python3.12, Python 3.12.3, python3-minimal, 
3.12.3-0ubuntu2
  PythonDetails: N/A
  RelatedPackageVersions:
-  dpkg 1.22.6ubuntu6.1
-  apt  2.8.3
+  dpkg 1.22.6ubuntu6.1
+  apt  2.8.3
  SourcePackage: base-files
  Title: package base-files 13ubuntu10.2 failed to install/upgrade: new 
base-files package pre-installation script subprocess returned error exit 
status 1
  UpgradeStatus: Upgraded to noble on 2025-01-15 (303 days ago)

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2131303

Title:
  package base-files 13ubuntu10.2 failed to install/upgrade: new base-
  files package pre-installation script subprocess returned error exit
  status 1: /lib32 is a dangling symbolic link

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/base-files/+bug/2131303/+subscriptions


-- 
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to