mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-16 23:03:40 +01:00
Merge pull request #108032 from andir/systemd-dlopen
systemd: patch runtime dlopen calls
This commit is contained in:
commit
4d36ba1d43
2 changed files with 86 additions and 0 deletions
|
@ -13,6 +13,8 @@ import ./make-test-python.nix ({ pkgs, ... }:
|
|||
testScript = ''
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
|
||||
machine.succeed("journalctl --grep=systemd")
|
||||
|
||||
machine.succeed(
|
||||
"${pkgs.curl}/bin/curl -s localhost:19531/machine | ${pkgs.jq}/bin/jq -e '.hostname == \"machine\"'"
|
||||
)
|
||||
|
|
|
@ -160,6 +160,90 @@ stdenv.mkDerivation {
|
|||
--replace \
|
||||
"find_program('objcopy'" \
|
||||
"find_program('${stdenv.cc.bintools.targetPrefix}objcopy'"
|
||||
'' + (let
|
||||
|
||||
# The folllowing dlopen patches ensure that all the features that are
|
||||
# implemented via dlopen(3) are available (or explicitly deactivated) by
|
||||
# pointing dlopen to the absolute store path instead of relying on the
|
||||
# linkers runtime lookup code.
|
||||
#
|
||||
# All of the dlopen calls have to be handled. When new ones are introduced
|
||||
# by upstream (or one of our patches) they must be explicitly declared,
|
||||
# otherwise the build will fail.
|
||||
#
|
||||
# As of systemd version 247 we've seen a few errors like `libpcre2.… not
|
||||
# found` when using e.g. --grep with journalctl. Those errors should
|
||||
# become less unexpected now.
|
||||
#
|
||||
# There are generally two classes of dlopen(3) calls. Those that we want to
|
||||
# support and those that should be deactivated / unsupported. This change
|
||||
# enforces that we handle all dlopen calls explicitly. Meaning: There is
|
||||
# not a single dlopen call in the source code tree that we did not
|
||||
# explicitly handle.
|
||||
#
|
||||
# In order to do this we introduced a list of attributes that maps from
|
||||
# shared object name to the package that contains them. The package can be
|
||||
# null meaning the reference should be nuked and the shared object will
|
||||
# never be loadable during runtime (because it points at an invalid store
|
||||
# path location).
|
||||
#
|
||||
# To get a list of dynamically loaded libraries issue something like
|
||||
# `grep -ri 'dlopen("lib' $src` and update the below list.
|
||||
dlopenLibs = [
|
||||
# We did never provide support for libxkbcommon & qrencode
|
||||
{ name = "libxkbcommon.so.0"; pkg = null; }
|
||||
{ name = "libqrencode.so.4"; pkg = null; }
|
||||
|
||||
# We did not provide libpwquality before so it is safe to disable it for
|
||||
# now.
|
||||
{ name = "libpwquality.so.1"; pkg = null; }
|
||||
|
||||
# Only include cryptsetup if it is enabled. We might not be able to
|
||||
# provide it during "bootstrap" in e.g. the minimal systemd build as
|
||||
# cryptsetup has udev (aka systemd) in it's dependencies.
|
||||
{ name = "libcryptsetup.so.12"; pkg = if withCryptsetup then cryptsetup else null; }
|
||||
|
||||
# We are using libidn2 so we only provide that and ignore the others.
|
||||
# Systemd does this decision during configure time and uses ifdef's to
|
||||
# enable specific branches. We can safely ignore (nuke) the libidn "v1"
|
||||
# libraries.
|
||||
{ name = "libidn2.so.0"; pkg = libidn2; }
|
||||
{ name = "libidn.so.12"; pkg = null; }
|
||||
{ name = "libidn.so.11"; pkg = null; }
|
||||
|
||||
# journalctl --grep requires libpcre so lets provide it
|
||||
{ name = "libpcre2-8.so.0"; pkg = pcre2; }
|
||||
];
|
||||
|
||||
patchDlOpen = dl: let
|
||||
library = "${lib.makeLibraryPath [dl.pkg]}/${dl.name}";
|
||||
in if dl.pkg == null then ''
|
||||
# remove the dependency on the library by replacing it with an invalid path
|
||||
for file in $(grep -lr 'dlopen("${dl.name}"' src); do
|
||||
echo "patching dlopen(\"${dl.name}\", …) in $file to an invalid store path ("/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-not-implemented/${dl.name}")…"
|
||||
substituteInPlace "$file" --replace 'dlopen("${dl.name}"' 'dlopen("/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-not-implemented/${dl.name}"'
|
||||
done
|
||||
'' else ''
|
||||
# ensure that the library we provide actually exists
|
||||
if ! [ -e ${library} ]; then
|
||||
echo 'The shared library `${library}` does not exist but was given as subtitute for `${dl.name}`'
|
||||
exit 1
|
||||
fi
|
||||
# make the path to the dependency explicit
|
||||
for file in $(grep -lr 'dlopen("${dl.name}"' src); do
|
||||
echo "patching dlopen(\"${dl.name}\", …) in $file to ${library}…"
|
||||
substituteInPlace "$file" --replace 'dlopen("${dl.name}"' 'dlopen("${library}"'
|
||||
done
|
||||
'';
|
||||
in # patch all the dlopen calls to contain absolute paths to the libraries
|
||||
lib.concatMapStringsSep "\n" patchDlOpen dlopenLibs)
|
||||
# finally ensure that there are no left-over dlopen calls that we didn't handle
|
||||
+ ''
|
||||
if grep -qr 'dlopen("[^/]' src; then
|
||||
echo "Found unhandled dlopen calls: "
|
||||
grep -r 'dlopen("[^/]' src
|
||||
exit 1
|
||||
fi
|
||||
'';
|
||||
|
||||
outputs = [ "out" "man" "dev" ];
|
||||
|
|
Loading…
Reference in a new issue