diff options
author | Romain Geissler <romain.geissler@amadeus.com> | 2023-06-20 18:06:31 +0200 |
---|---|---|
committer | Luca Boccassi <luca.boccassi@gmail.com> | 2023-06-21 20:07:20 +0200 |
commit | 21a2c735e2bfdc3bfdc42f894d6e3d00f4a38dcd (patch) | |
tree | fe420b99c8d852f9702026548cd88d0c238fd739 /src/shared/elf-util.c | |
parent | Merge pull request #27942 from DaanDeMeyer/root-ephemeral (diff) | |
download | systemd-21a2c735e2bfdc3bfdc42f894d6e3d00f4a38dcd.tar.xz systemd-21a2c735e2bfdc3bfdc42f894d6e3d00f4a38dcd.zip |
elf-util: discard PT_LOAD segment early based on the start address.
Indeed when iterating over all the PT_LOAD segment of the core dump
while trying to look for the elf headers of a given module, we iterate
over them all and try to use the first one for which we can parse a
package metadata, but the start address is never taken into account,
so absolutely nothing guarantees we actually parse the right ELF header
of the right module we are currently iterating on.
This was tested like this:
- Create a core dump using sleep on a fedora 37 container, with an
explicit LD_PRELOAD of a library having a valid package metadata:
podman run -t -i --rm -v $(pwd):$(pwd) -w $(pwd) fedora:37 bash -x -c \
'LD_PRELOAD=libreadline.so.8 sleep 1000 & SLEEP_PID="$!" && sleep 1 && kill -11 "${SLEEP_PID}" && mv "core.${SLEEP_PID}" the-core'
- Then from a fedora 38 container with systemd installed, the resulting
core dump has been passed to systemd-coredump with and without this
patch. Without this patch, we get:
Module /usr/bin/sleep from rpm bash-5.2.15-3.fc38.x86_64
Module /usr/lib64/libtinfo.so.6.3 from rpm coreutils-9.1-8.fc37.x86_64
Module /usr/lib64/libc.so.6 from rpm coreutils-9.1-8.fc37.x86_64
Module /usr/lib64/libreadline.so.8.2 from rpm coreutils-9.1-8.fc37.x86_64
Module /usr/lib64/ld-linux-x86-64.so.2 from rpm coreutils-9.1-8.fc37.x86_64
While with this patch we get:
Module /usr/bin/sleep from rpm bash-5.2.15-3.fc38.x86_64
Module /usr/lib64/libtinfo.so.6.3 from rpm ncurses-6.3-5.20220501.fc37.x86_64
Module /usr/lib64/libreadline.so.8.2 from rpm readline-8.2-2.fc37.x86_64
So the parsed package metadata reported by systemd-coredump when the module
files are not found on the host (ie the case of crash inside a container) are
now correct. The inconsistency of the first module in the above example
(sleep is indeed not provided by the bash package) can be ignored as it
is a consequence of how this was tested.
In addition to this, this also fixes the performance issue of
systemd-coredump in case of the crashing process uses a large number of
shared libraries and having no package metadata, as reported in
https://sourceware.org/pipermail/elfutils-devel/2023q2/006225.html.
Diffstat (limited to 'src/shared/elf-util.c')
-rw-r--r-- | src/shared/elf-util.c | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/src/shared/elf-util.c b/src/shared/elf-util.c index 5d652d7ac7..9ab580f2fe 100644 --- a/src/shared/elf-util.c +++ b/src/shared/elf-util.c @@ -538,6 +538,10 @@ static int module_callback(Dwfl_Module *mod, void **userdata, const char *name, if (!program_header || program_header->p_type != PT_LOAD) continue; + /* This PT_LOAD segment doesn't contain the start address, so it can't be the module we are looking for. */ + if (start < program_header->p_vaddr || start >= program_header->p_vaddr + program_header->p_memsz) + continue; + /* Now get a usable Elf reference, and parse the notes from it. */ data = sym_elf_getdata_rawchunk(elf, program_header->p_offset, |