From d726b8db0f9c9bd98a1237eeadb78f959ade82d4 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Wed, 18 Dec 2024 13:03:17 -0600 Subject: [PATCH] libpkg: fall back to Linux for ELF shlib parsing If the target ABI is either Linux or FreeBSD and the target OS of a shared library ELF file cannot be determined, assume that it is a Linux ELF file. It is unfortunately impossible to reliably determine whether a shared library targets Linux. See the new comment in pkg_elf.c for further details. Sponsored by: The FreeBSD Foundation --- libpkg/pkg_elf.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/libpkg/pkg_elf.c b/libpkg/pkg_elf.c index 644aa917a..105c96f27 100644 --- a/libpkg/pkg_elf.c +++ b/libpkg/pkg_elf.c @@ -151,15 +151,43 @@ analyse_elf(struct pkg *pkg, const char *fpath) goto cleanup; /* not a dynamically linked elf: no results */ } - /* A shared object for use with dlopen(3) may lack a NOTE section and - will therefore have unknown elf_abi.os. */ struct pkg_abi elf_abi; elf_parse_abi(e, &elfhdr, &elf_abi); - if (elf_abi.os == PKG_OS_UNKNOWN || elf_abi.arch == PKG_ARCH_UNKNOWN) { + if (elf_abi.arch == PKG_ARCH_UNKNOWN) { ret = EPKG_END; goto cleanup; } + if (elf_abi.os == PKG_OS_UNKNOWN) { + /* There is no reliable way to identify shared libraries targeting Linux. + * It would be possible to reliably identify Linux executables by checking + * the dynamic linker path in DT_INTERP. Shared libraries however do not + * have DT_INTERP set. + * + * Reading the notes section for NT_GNU_ABI_TAG is not sufficient either + * as this is only required for executables, not shared libraries. + * See https://refspecs.linuxfoundation.org/LSB_1.2.0/gLSB/noteabitag.html + * + * Therefore, if pkg is targeting Linux assume that ELF files with unknown + * target OS are also targeting Linux. + * + * Furthermore, if pkg is targeting FreeBSD also assume that ELF + * files with unknown target OS are targeting Linux. This is consistent + * with the behavior of the FreeBSD kernel, which falls back to Linux by + * default if it is unable to determine the target OS of an ELF file. + * (This behavior can be overridden with a fallback_brand sysctl.) + * + * We could add a pkg option to configure the fallback OS + * in the future if necessary. + */ + if (ctx.abi.os == PKG_OS_LINUX || ctx.abi.os == PKG_OS_FREEBSD) { + elf_abi.os = PKG_OS_LINUX; + } else { + ret = EPKG_END; + goto cleanup; + } + } + enum pkg_shlib_flags flags = pkg_shlib_flags_from_abi(&elf_abi); if ((flags & PKG_SHLIB_FLAGS_COMPAT_LINUX) == 0 && elf_abi.os != ctx.abi.os) { ret = EPKG_END;