analyze: Add dlopen-metadata verb
systemd-analyze dlopen-metadata will show dlopen metadata in the ELF binary.
This commit is contained in:
@@ -915,6 +915,16 @@ alias.service:7: Unknown key name 'MysteryKey' in section 'Service', ignoring.
|
||||
</example>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title><command>systemd-analyze dlopen-metadata <replaceable>FILE</replaceable></command></title>
|
||||
|
||||
<para>This command will load the specified file, and if it is an ELF object (executables,
|
||||
libraries, core files, etc.) it will parse the embedded dlopen metadata, if any, and print
|
||||
it in a table or json format. See the
|
||||
<ulink url="https://systemd.io/ELF_DLOPEN_METADATA/">
|
||||
dlopen() Metadata for ELF Files</ulink> document for more information.</para>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title><command>systemd-analyze fdstore <replaceable>UNIT</replaceable>...</command></title>
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "sd-json.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "analyze.h"
|
||||
#include "analyze-dlopen-metadata.h"
|
||||
#include "chase.h"
|
||||
#include "elf-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "format-table.h"
|
||||
#include "json-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
int verb_dlopen_metadata(int argc, char *argv[], void *userdata) {
|
||||
int r;
|
||||
|
||||
_cleanup_free_ char *abspath = NULL;
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
fd = chase_and_open(argv[1], arg_root, CHASE_PREFIX_ROOT, O_RDONLY|O_CLOEXEC, &abspath);
|
||||
if (fd < 0)
|
||||
return log_error_errno(fd, "Could not open \"%s\": %m", argv[1]);
|
||||
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *dlopen_metadata = NULL;
|
||||
r = parse_elf_object(
|
||||
fd,
|
||||
abspath,
|
||||
arg_root,
|
||||
/* fork_disable_dump= */ false,
|
||||
/* ret= */ NULL,
|
||||
NULL,
|
||||
&dlopen_metadata);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Parsing \"%s\" as ELF object failed: %m", abspath);
|
||||
|
||||
if (!dlopen_metadata)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENODATA), "%s does not contain any .note.dlopen sections", argv[1]);
|
||||
|
||||
if (sd_json_format_enabled(arg_json_format_flags))
|
||||
return sd_json_variant_dump(dlopen_metadata, arg_json_format_flags, stdout, NULL);
|
||||
|
||||
_cleanup_(table_unrefp) Table *t = NULL;
|
||||
t = table_new("feature", "description", "soname", "priority");
|
||||
if (!t)
|
||||
return log_oom();
|
||||
|
||||
table_set_ersatz_string(t, TABLE_ERSATZ_NA);
|
||||
|
||||
sd_json_variant *z;
|
||||
JSON_VARIANT_ARRAY_FOREACH(z, dlopen_metadata) {
|
||||
_cleanup_strv_free_ char **sonames = NULL;
|
||||
|
||||
r = sd_json_variant_strv(sd_json_variant_by_key(z, "soname"), &sonames);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to extract sonames from dlopen metadata: %m");
|
||||
|
||||
r = table_add_many(
|
||||
t,
|
||||
TABLE_STRING, sd_json_variant_string(sd_json_variant_by_key(z, "feature")),
|
||||
TABLE_STRING, sd_json_variant_string(sd_json_variant_by_key(z, "description")),
|
||||
TABLE_STRV_WRAPPED, sonames,
|
||||
TABLE_STRING, sd_json_variant_string(sd_json_variant_by_key(z, "priority")));
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
}
|
||||
|
||||
r = table_print(t, NULL);
|
||||
if (r < 0)
|
||||
return table_log_print_error(r);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
int verb_dlopen_metadata(int argc, char *argv[], void *userdata);
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "analyze-compare-versions.h"
|
||||
#include "analyze-condition.h"
|
||||
#include "analyze-critical-chain.h"
|
||||
#include "analyze-dlopen-metadata.h"
|
||||
#include "analyze-dot.h"
|
||||
#include "analyze-dump.h"
|
||||
#include "analyze-exit-status.h"
|
||||
@@ -798,6 +799,7 @@ static int run(int argc, char *argv[]) {
|
||||
{ "timespan", 2, VERB_ANY, 0, verb_timespan },
|
||||
{ "security", VERB_ANY, VERB_ANY, 0, verb_security },
|
||||
{ "inspect-elf", 2, VERB_ANY, 0, verb_elf_inspection },
|
||||
{ "dlopen-metadata", 2, 2, 0, verb_dlopen_metadata },
|
||||
{ "malloc", VERB_ANY, VERB_ANY, 0, verb_malloc },
|
||||
{ "fdstore", 2, VERB_ANY, 0, verb_fdstore },
|
||||
{ "image-policy", 2, 2, 0, verb_image_policy },
|
||||
|
||||
@@ -10,6 +10,7 @@ systemd_analyze_sources = files(
|
||||
'analyze-compare-versions.c',
|
||||
'analyze-condition.c',
|
||||
'analyze-critical-chain.c',
|
||||
'analyze-dlopen-metadata.c',
|
||||
'analyze-dot.c',
|
||||
'analyze-dump.c',
|
||||
'analyze-exit-status.c',
|
||||
|
||||
@@ -1006,7 +1006,16 @@ systemd-analyze security --threshold=25 --offline=true \
|
||||
rm /tmp/img/usr/lib/systemd/system/testfile.service
|
||||
|
||||
if systemd-analyze --version | grep -q -F "+ELFUTILS"; then
|
||||
systemd-analyze inspect-elf /lib/systemd/systemd
|
||||
systemd-analyze inspect-elf --json=short /lib/systemd/systemd | grep -q -F '"elfType":"executable"'
|
||||
|
||||
# For some unknown reason the .note.dlopen sections are removed when building with sanitizers, so only
|
||||
# run this test if we're not running under sanitizers.
|
||||
if [[ ! -v ASAN_OPTIONS ]]; then
|
||||
shared="$(ldd /lib/systemd/systemd | grep shared | cut -d' ' -f3)"
|
||||
systemd-analyze dlopen-metadata "$shared"
|
||||
systemd-analyze dlopen-metadata --json=short "$shared"
|
||||
fi
|
||||
fi
|
||||
|
||||
systemd-analyze --threshold=90 security systemd-journald.service
|
||||
|
||||
Reference in New Issue
Block a user