Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
core-initrd: maintain an explict list of ignored dlopen features
We should not ignore libraries including suggested one. We should
list what we ignore.
  • Loading branch information
valentindavid committed Sep 24, 2026
commit 2c0d149655393ffc224c079a61776358a5051ccc
81 changes: 50 additions & 31 deletions core-initrd/26.10/bin/ubuntu-core-initramfs
Original file line number Diff line number Diff line change
Expand Up @@ -391,8 +391,14 @@ def install_systemd_files(dest_dir, sysroot, ubuntu_release):


def install_busybox(dest_dir, sysroot):
install_file_to_path("/usr/lib/initramfs-tools/bin/busybox", dest_dir,
"usr/bin/busybox", sysroot)
if os.path.exists("/usr/lib/initramfs-tools/bin/busybox"):
# Up to 26.04 we can use a smaller busybox
install_file_to_path("/usr/lib/initramfs-tools/bin/busybox", dest_dir,
"usr/bin/busybox", sysroot)
else:
# From 26.10, busybox-initramfs does not exist
install_file_to_path("/usr/bin/busybox", dest_dir,
"usr/bin/busybox", sysroot)
# Commands we want for busybox (static for more control and to help
# with cross-building).
cmds = ["[", "[[", "acpid", "arch", "ascii", "ash", "awk", "base32", "basename",
Expand Down Expand Up @@ -473,6 +479,7 @@ def install_misc(dest_dir, sysroot, deb_arch, ubuntu_release):
if release_higher_or_equal(ubuntu_release, (26, 10)):
files.append("/usr/lib/" + deb_arch + "/libcurl.so.4")
files += glob.glob("/usr/lib/" + deb_arch + "/libtss2*.so.*")
files.append("/usr/lib/" + deb_arch + "/libgcrypt.so.20")

# Include xkb-data layouts for plymouth
files += glob.glob("/usr/share/X11/xkb/**/*", recursive=True)
Expand Down Expand Up @@ -664,12 +671,37 @@ def create_initrd_pkg_list(dest_dir, sysroot):
return manifest_path


def max_priority(a, b):
if "required" in (a, b):
return "required"
elif "recommended" in (a, b):
return "recommend"
else:
return "suggested"

# verify_missing_dlopen looks at the .notes.dlopen section of ELF
# binaries to find libraries that are not in the dynamic section, and
# that will be loaded with dynamically dlopen when needed.
# See https://systemd.io/ELF_DLOPEN_METADATA/
def verify_missing_dlopen(destdir, libdir):
def verify_missing_dlopen(destdir, libdir, ubuntu_release):
ignored_dlopen_features = [
]

if ubuntu_release == (26, 10):
ignored_dlopen_features += [
"archive",
"bzip2",
"dw",
"fido2",
"microhttpd",
"p11-kit",
"pwquality",
"qrencode",
]
]

missing = {}
priorities = {}
for dirpath, dirs, files in os.walk(destdir):
for f in files:
path = os.path.join(dirpath, f)
Expand All @@ -683,41 +715,29 @@ def verify_missing_dlopen(destdir, libdir):
json_doc = b'\n'.join([s for s in split if not s[:1] == b'#'])
doc = json.loads(json_doc)
for dep in doc:
feature = dep["feature"]
if feature in ignored_dlopen_features:
continue
sonames = dep["soname"]
priority = dep["priority"]
priorities[feature] = max_priority(dep["priority"], priorities.get(feature, "suggested"))

found_sonames = []
for soname in sonames:
dest = os.path.join(destdir, os.path.relpath(libdir, "/"), soname)
if os.path.exists(os.path.join(destdir, dest)):
found_sonames.append(soname)
if not found_sonames:
# We did not find any library.
# In this case we need to mark all sonames as
# missing. This is required because some features
# may have common subset of sonames and those
# features might have different priorities.
for soname in sonames:
current_priority = missing.get(soname)
if current_priority == "required":
continue
elif current_priority == "recommended" and priority not in ["required"]:
continue
elif current_priority == "suggested" and priority not in ["required", "recommended"]:
continue
else:
missing[soname] = priority

fatal = False
missing[feature] = sonames

if missing:
print("WARNING: These sonames are missing:", file=sys.stderr)
for m, priority in missing.items():
print(f" * {m} ({priority})", file=sys.stderr)
if priority in ["required", "recommended"]:
fatal = True
if fatal:
print("WARNING: Some missing sonames are required or recommended. Failing.", file=sys.stderr)
print("ERROR: These sonames are missing:", file=sys.stderr)
for feature, sonames in missing.items():
sonames_str = ', '.join(sonames)
priority = priorities[feature]
print(f" * {priority} {feature} ({sonames_str})", file=sys.stderr)

return not fatal
return not missing


def mkcpio(path, output, *, compress=True):
Expand Down Expand Up @@ -865,9 +885,8 @@ def create_initrd(parser, args):
)
check_call(["depmod", "-a", "-b", main, args.kernelver])

if release_higher_or_equal(ubuntu_release, (24, 10)):
if not verify_missing_dlopen(main, os.path.join("/usr/lib", deb_arch)):
sys.exit(1)
if not verify_missing_dlopen(main, os.path.join("/usr/lib", deb_arch), ubuntu_release):
sys.exit(1)

# Create manifest with packages with files included in the initramfs
manifest_path = create_initrd_pkg_list(main, rootfs)
Expand Down
3 changes: 2 additions & 1 deletion core-initrd/26.10/debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Architecture: amd64 arm64 armhf riscv64
Depends: ${python3:Depends}, ${misc:Depends}, dracut-core (>= 051-1),
cpio,
python3:any,
busybox-initramfs,
busybox-static,
zstd,
sbsigntool,
linux-firmware,
Expand All @@ -33,6 +33,7 @@ Depends: ${python3:Depends}, ${misc:Depends}, dracut-core (>= 051-1),
kmod,
libblkid1,
libbpf1,
libcurl4,
libgcc-s1,
libkmod2,
mount,
Expand Down
Loading