mirror of
https://github.com/systemd/systemd
synced 2025-11-18 00:04:46 +01:00
Compare commits
No commits in common. "b5d63191cabc4b60744d743c28bc2f9a2419e711" and "f54d72c2b6463d3ba6d418cb710db5fed80e8fc0" have entirely different histories.
b5d63191ca
...
f54d72c2b6
@ -611,10 +611,6 @@ mouse:usb:v046dpc548:name:Logitech USB Receiver Mouse:*
|
|||||||
mouse:bluetooth:v046dpb035:name:MX Master 3S B Mouse:*
|
mouse:bluetooth:v046dpb035:name:MX Master 3S B Mouse:*
|
||||||
MOUSE_DPI=1000@142
|
MOUSE_DPI=1000@142
|
||||||
|
|
||||||
# Logitech MX Master 4 (via Bluetooth)
|
|
||||||
mouse:bluetooth:v046dpb042:name:MX Master 4 Mouse:*
|
|
||||||
MOUSE_DPI=1000@142
|
|
||||||
|
|
||||||
# Logitech MX Ergo
|
# Logitech MX Ergo
|
||||||
mouse:usb:v046dp406f:name:Logitech MX Ergo:*
|
mouse:usb:v046dp406f:name:Logitech MX Ergo:*
|
||||||
mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:406f:*
|
mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:406f:*
|
||||||
|
|||||||
@ -915,16 +915,6 @@ alias.service:7: Unknown key name 'MysteryKey' in section 'Service', ignoring.
|
|||||||
</example>
|
</example>
|
||||||
</refsect2>
|
</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>
|
<refsect2>
|
||||||
<title><command>systemd-analyze fdstore <replaceable>UNIT</replaceable>...</command></title>
|
<title><command>systemd-analyze fdstore <replaceable>UNIT</replaceable>...</command></title>
|
||||||
|
|
||||||
|
|||||||
@ -1,72 +0,0 @@
|
|||||||
/* 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;
|
|
||||||
}
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
int verb_dlopen_metadata(int argc, char *argv[], void *userdata);
|
|
||||||
@ -27,14 +27,7 @@ static int analyze_elf(char **filenames, sd_json_format_flags_t json_flags) {
|
|||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return log_error_errno(fd, "Could not open \"%s\": %m", *filename);
|
return log_error_errno(fd, "Could not open \"%s\": %m", *filename);
|
||||||
|
|
||||||
r = parse_elf_object(
|
r = parse_elf_object(fd, abspath, arg_root, /* fork_disable_dump= */false, &stacktrace, &package_metadata);
|
||||||
fd,
|
|
||||||
abspath,
|
|
||||||
arg_root,
|
|
||||||
/* fork_disable_dump= */ false,
|
|
||||||
&stacktrace,
|
|
||||||
&package_metadata,
|
|
||||||
/* ret_dlopen_metadata= */ NULL);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Parsing \"%s\" as ELF object failed: %m", abspath);
|
return log_error_errno(r, "Parsing \"%s\" as ELF object failed: %m", abspath);
|
||||||
|
|
||||||
|
|||||||
@ -22,7 +22,6 @@
|
|||||||
#include "analyze-compare-versions.h"
|
#include "analyze-compare-versions.h"
|
||||||
#include "analyze-condition.h"
|
#include "analyze-condition.h"
|
||||||
#include "analyze-critical-chain.h"
|
#include "analyze-critical-chain.h"
|
||||||
#include "analyze-dlopen-metadata.h"
|
|
||||||
#include "analyze-dot.h"
|
#include "analyze-dot.h"
|
||||||
#include "analyze-dump.h"
|
#include "analyze-dump.h"
|
||||||
#include "analyze-exit-status.h"
|
#include "analyze-exit-status.h"
|
||||||
@ -799,7 +798,6 @@ static int run(int argc, char *argv[]) {
|
|||||||
{ "timespan", 2, VERB_ANY, 0, verb_timespan },
|
{ "timespan", 2, VERB_ANY, 0, verb_timespan },
|
||||||
{ "security", VERB_ANY, VERB_ANY, 0, verb_security },
|
{ "security", VERB_ANY, VERB_ANY, 0, verb_security },
|
||||||
{ "inspect-elf", 2, VERB_ANY, 0, verb_elf_inspection },
|
{ "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 },
|
{ "malloc", VERB_ANY, VERB_ANY, 0, verb_malloc },
|
||||||
{ "fdstore", 2, VERB_ANY, 0, verb_fdstore },
|
{ "fdstore", 2, VERB_ANY, 0, verb_fdstore },
|
||||||
{ "image-policy", 2, 2, 0, verb_image_policy },
|
{ "image-policy", 2, 2, 0, verb_image_policy },
|
||||||
|
|||||||
@ -10,7 +10,6 @@ systemd_analyze_sources = files(
|
|||||||
'analyze-compare-versions.c',
|
'analyze-compare-versions.c',
|
||||||
'analyze-condition.c',
|
'analyze-condition.c',
|
||||||
'analyze-critical-chain.c',
|
'analyze-critical-chain.c',
|
||||||
'analyze-dlopen-metadata.c',
|
|
||||||
'analyze-dot.c',
|
'analyze-dot.c',
|
||||||
'analyze-dump.c',
|
'analyze-dump.c',
|
||||||
'analyze-exit-status.c',
|
'analyze-exit-status.c',
|
||||||
|
|||||||
@ -689,8 +689,7 @@ int coredump_submit(
|
|||||||
root,
|
root,
|
||||||
/* fork_disable_dump= */ skip, /* avoid loops */
|
/* fork_disable_dump= */ skip, /* avoid loops */
|
||||||
&stacktrace,
|
&stacktrace,
|
||||||
&json_metadata,
|
&json_metadata);
|
||||||
/* ret_dlopen_metadata= */ NULL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -287,6 +287,8 @@ int vl_method_get_memberships(sd_varlink *link, sd_json_variant *parameters, sd_
|
|||||||
return sd_varlink_error(link, "io.systemd.UserDatabase.BadService", NULL);
|
return sd_varlink_error(link, "io.systemd.UserDatabase.BadService", NULL);
|
||||||
|
|
||||||
if (p.user_name) {
|
if (p.user_name) {
|
||||||
|
const char *last = NULL;
|
||||||
|
|
||||||
r = manager_get_home_by_name(m, p.user_name, &h);
|
r = manager_get_home_by_name(m, p.user_name, &h);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -294,37 +296,40 @@ int vl_method_get_memberships(sd_varlink *link, sd_json_variant *parameters, sd_
|
|||||||
return sd_varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
return sd_varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
||||||
|
|
||||||
if (p.group_name) {
|
if (p.group_name) {
|
||||||
if (!strv_contains(h->record->member_of, p.group_name) &&
|
if (!strv_contains(h->record->member_of, p.group_name))
|
||||||
!user_record_matches_user_name(h->record, p.group_name))
|
|
||||||
return sd_varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
return sd_varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
||||||
|
|
||||||
return sd_varlink_replybo(
|
return sd_varlink_replybo(
|
||||||
link,
|
link,
|
||||||
SD_JSON_BUILD_PAIR_STRING("userName", h->user_name),
|
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(h->user_name)),
|
||||||
SD_JSON_BUILD_PAIR_STRING("groupName", p.group_name));
|
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(p.group_name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
STRV_FOREACH(i, h->record->member_of) {
|
STRV_FOREACH(i, h->record->member_of) {
|
||||||
r = sd_varlink_notifybo(
|
if (last) {
|
||||||
link,
|
r = sd_varlink_notifybo(
|
||||||
SD_JSON_BUILD_PAIR_STRING("userName", h->user_name),
|
link,
|
||||||
SD_JSON_BUILD_PAIR_STRING("groupName", *i));
|
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(h->user_name)),
|
||||||
if (r < 0)
|
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(last)));
|
||||||
return r;
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
last = *i;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sd_varlink_replybo(
|
if (last)
|
||||||
link,
|
return sd_varlink_replybo(
|
||||||
SD_JSON_BUILD_PAIR_STRING("userName", h->user_name),
|
link,
|
||||||
SD_JSON_BUILD_PAIR_STRING("groupName", h->user_name));
|
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(h->user_name)),
|
||||||
|
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(last)));
|
||||||
|
|
||||||
} else if (p.group_name) {
|
} else if (p.group_name) {
|
||||||
const char *last = NULL;
|
const char *last = NULL;
|
||||||
|
|
||||||
HASHMAP_FOREACH(h, m->homes_by_uid) {
|
HASHMAP_FOREACH(h, m->homes_by_uid) {
|
||||||
|
|
||||||
if (!strv_contains(h->record->member_of, p.group_name) &&
|
if (!strv_contains(h->record->member_of, p.group_name))
|
||||||
!user_record_matches_user_name(h->record, p.group_name))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (last) {
|
if (last) {
|
||||||
@ -345,37 +350,34 @@ int vl_method_get_memberships(sd_varlink *link, sd_json_variant *parameters, sd_
|
|||||||
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(last)),
|
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(last)),
|
||||||
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(p.group_name)));
|
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(p.group_name)));
|
||||||
} else {
|
} else {
|
||||||
const char *last = NULL;
|
const char *last_user_name = NULL, *last_group_name = NULL;
|
||||||
|
|
||||||
HASHMAP_FOREACH(h, m->homes_by_uid) {
|
HASHMAP_FOREACH(h, m->homes_by_uid)
|
||||||
STRV_FOREACH(j, h->record->member_of) {
|
STRV_FOREACH(j, h->record->member_of) {
|
||||||
if (last) {
|
|
||||||
|
if (last_user_name) {
|
||||||
|
assert(last_group_name);
|
||||||
|
|
||||||
r = sd_varlink_notifybo(
|
r = sd_varlink_notifybo(
|
||||||
link,
|
link,
|
||||||
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(last)),
|
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(last_user_name)),
|
||||||
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(last)));
|
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(last_group_name)));
|
||||||
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
last = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_varlink_notifybo(
|
last_user_name = h->user_name;
|
||||||
link,
|
last_group_name = *j;
|
||||||
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(h->user_name)),
|
|
||||||
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(*j)));
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
last = h->user_name;
|
if (last_user_name) {
|
||||||
}
|
assert(last_group_name);
|
||||||
|
|
||||||
if (last)
|
|
||||||
return sd_varlink_replybo(
|
return sd_varlink_replybo(
|
||||||
link,
|
link,
|
||||||
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(last)),
|
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(last_user_name)),
|
||||||
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(last)));
|
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(last_group_name)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return sd_varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
return sd_varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
||||||
|
|||||||
@ -377,8 +377,6 @@ static int link_set_ip_forwarding(Link *link, int family) {
|
|||||||
if (FLAGS_SET(link->network->ip_masquerade, AF_TO_ADDRESS_FAMILY(family)) &&
|
if (FLAGS_SET(link->network->ip_masquerade, AF_TO_ADDRESS_FAMILY(family)) &&
|
||||||
link->manager->ip_forwarding[family == AF_INET6] < 0) {
|
link->manager->ip_forwarding[family == AF_INET6] < 0) {
|
||||||
|
|
||||||
log_link_notice(link, "IPMasquerade= is enabled on the interface, enabling the global IPv6Forwarding= setting, which may affect NDisc and DHCPv6 client on other interfaces.");
|
|
||||||
|
|
||||||
link->manager->ip_forwarding[family == AF_INET6] = true;
|
link->manager->ip_forwarding[family == AF_INET6] = true;
|
||||||
manager_set_ip_forwarding(link->manager, family);
|
manager_set_ip_forwarding(link->manager, family);
|
||||||
|
|
||||||
|
|||||||
@ -20,7 +20,6 @@
|
|||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
#include "format-util.h"
|
#include "format-util.h"
|
||||||
#include "io-util.h"
|
#include "io-util.h"
|
||||||
#include "json-util.h"
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "memstream-util.h"
|
#include "memstream-util.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
@ -187,7 +186,6 @@ typedef struct StackContext {
|
|||||||
unsigned n_thread;
|
unsigned n_thread;
|
||||||
unsigned n_frame;
|
unsigned n_frame;
|
||||||
sd_json_variant **package_metadata;
|
sd_json_variant **package_metadata;
|
||||||
sd_json_variant **dlopen_metadata;
|
|
||||||
Set **modules;
|
Set **modules;
|
||||||
} StackContext;
|
} StackContext;
|
||||||
|
|
||||||
@ -354,8 +352,8 @@ static void report_module_metadata(StackContext *c, const char *name, sd_json_va
|
|||||||
fputs("\n", c->m.f);
|
fputs("\n", c->m.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_metadata(const char *name, sd_json_variant *id_json, Elf *elf, bool *ret_interpreter_found, StackContext *c) {
|
static int parse_package_metadata(const char *name, sd_json_variant *id_json, Elf *elf, bool *ret_interpreter_found, StackContext *c) {
|
||||||
bool package_metadata_found = false, interpreter_found = false;
|
bool interpreter_found = false;
|
||||||
size_t n_program_headers;
|
size_t n_program_headers;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -410,7 +408,7 @@ static int parse_metadata(const char *name, sd_json_variant *id_json, Elf *elf,
|
|||||||
|
|
||||||
/* Package metadata might have different owners, but the
|
/* Package metadata might have different owners, but the
|
||||||
* magic ID is always the same. */
|
* magic ID is always the same. */
|
||||||
if (!IN_SET(note_header.n_type, ELF_PACKAGE_METADATA_ID, ELF_NOTE_DLOPEN_TYPE))
|
if (note_header.n_type != ELF_PACKAGE_METADATA_ID)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
_cleanup_free_ char *payload_0suffixed = NULL;
|
_cleanup_free_ char *payload_0suffixed = NULL;
|
||||||
@ -432,59 +430,46 @@ static int parse_metadata(const char *name, sd_json_variant *id_json, Elf *elf,
|
|||||||
return log_error_errno(r, "json_parse on \"%s\" failed: %m", strnull(esc));
|
return log_error_errno(r, "json_parse on \"%s\" failed: %m", strnull(esc));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (note_header.n_type == ELF_PACKAGE_METADATA_ID) {
|
/* If we have a build-id, merge it in the same JSON object so that it appears all
|
||||||
/* If we have a build-id, merge it in the same JSON object so that it appears all
|
* nicely together in the logs/metadata. */
|
||||||
* nicely together in the logs/metadata. */
|
if (id_json) {
|
||||||
if (id_json) {
|
r = sd_json_variant_merge_object(&v, id_json);
|
||||||
r = sd_json_variant_merge_object(&v, id_json);
|
|
||||||
if (r < 0)
|
|
||||||
return log_error_errno(r, "sd_json_variant_merge of package meta with buildId failed: %m");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Pretty-print to the buffer, so that the metadata goes as plaintext in the
|
|
||||||
* journal. */
|
|
||||||
report_module_metadata(c, name, v);
|
|
||||||
|
|
||||||
/* Then we build a new object using the module name as the key, and merge it
|
|
||||||
* with the previous parses, so that in the end it all fits together in a single
|
|
||||||
* JSON blob. */
|
|
||||||
r = sd_json_buildo(&w, SD_JSON_BUILD_PAIR(name, SD_JSON_BUILD_VARIANT(v)));
|
|
||||||
if (r < 0)
|
|
||||||
return log_error_errno(r, "Failed to build JSON object: %m");
|
|
||||||
|
|
||||||
r = sd_json_variant_merge_object(c->package_metadata, w);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "sd_json_variant_merge of package meta with buildId failed: %m");
|
return log_error_errno(r, "sd_json_variant_merge of package meta with buildId failed: %m");
|
||||||
|
|
||||||
package_metadata_found = true;
|
|
||||||
} else if (c->dlopen_metadata) {
|
|
||||||
sd_json_variant *z;
|
|
||||||
|
|
||||||
JSON_VARIANT_ARRAY_FOREACH(z, v) {
|
|
||||||
r = sd_json_variant_append_array(c->dlopen_metadata, z);
|
|
||||||
if (r < 0)
|
|
||||||
return log_error_errno(r, "Failed to append entry to dlopen metadata: %m");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Pretty-print to the buffer, so that the metadata goes as plaintext in the
|
||||||
|
* journal. */
|
||||||
|
report_module_metadata(c, name, v);
|
||||||
|
|
||||||
|
/* Then we build a new object using the module name as the key, and merge it
|
||||||
|
* with the previous parses, so that in the end it all fits together in a single
|
||||||
|
* JSON blob. */
|
||||||
|
r = sd_json_buildo(&w, SD_JSON_BUILD_PAIR(name, SD_JSON_BUILD_VARIANT(v)));
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to build JSON object: %m");
|
||||||
|
|
||||||
|
r = sd_json_variant_merge_object(c->package_metadata, w);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "sd_json_variant_merge of package meta with buildId failed: %m");
|
||||||
|
|
||||||
/* Finally stash the name, so we avoid double visits. */
|
/* Finally stash the name, so we avoid double visits. */
|
||||||
r = set_put_strdup(c->modules, name);
|
r = set_put_strdup(c->modules, name);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "set_put_strdup failed: %m");
|
return log_error_errno(r, "set_put_strdup failed: %m");
|
||||||
|
|
||||||
if (!c->dlopen_metadata) {
|
if (ret_interpreter_found)
|
||||||
if (ret_interpreter_found)
|
*ret_interpreter_found = interpreter_found;
|
||||||
*ret_interpreter_found = interpreter_found;
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret_interpreter_found)
|
if (ret_interpreter_found)
|
||||||
*ret_interpreter_found = interpreter_found;
|
*ret_interpreter_found = interpreter_found;
|
||||||
|
|
||||||
return c->dlopen_metadata ? 0 : package_metadata_found;
|
/* Didn't find package metadata for this module - that's ok, just go to the next. */
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the build-id out of an ELF object or a dwarf core module. */
|
/* Get the build-id out of an ELF object or a dwarf core module. */
|
||||||
@ -550,7 +535,7 @@ static int module_callback(Dwfl_Module *mod, void **userdata, const char *name,
|
|||||||
* to the ELF object first. We might be lucky and just get it from elfutils. */
|
* to the ELF object first. We might be lucky and just get it from elfutils. */
|
||||||
elf = sym_dwfl_module_getelf(mod, &bias);
|
elf = sym_dwfl_module_getelf(mod, &bias);
|
||||||
if (elf) {
|
if (elf) {
|
||||||
r = parse_metadata(name, id_json, elf, NULL, c);
|
r = parse_package_metadata(name, id_json, elf, NULL, c);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return DWARF_CB_ABORT;
|
return DWARF_CB_ABORT;
|
||||||
if (r > 0)
|
if (r > 0)
|
||||||
@ -605,8 +590,7 @@ static int module_callback(Dwfl_Module *mod, void **userdata, const char *name,
|
|||||||
_cleanup_(elf_endp) Elf *memelf = sym_elf_memory(data->d_buf, data->d_size);
|
_cleanup_(elf_endp) Elf *memelf = sym_elf_memory(data->d_buf, data->d_size);
|
||||||
if (!memelf)
|
if (!memelf)
|
||||||
continue;
|
continue;
|
||||||
|
r = parse_package_metadata(name, id_json, memelf, NULL, c);
|
||||||
r = parse_metadata(name, id_json, memelf, NULL, c);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return DWARF_CB_ABORT;
|
return DWARF_CB_ABORT;
|
||||||
if (r > 0)
|
if (r > 0)
|
||||||
@ -616,12 +600,7 @@ static int module_callback(Dwfl_Module *mod, void **userdata, const char *name,
|
|||||||
return DWARF_CB_OK;
|
return DWARF_CB_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_core(
|
static int parse_core(int fd, const char *root, char **ret, sd_json_variant **ret_package_metadata) {
|
||||||
int fd,
|
|
||||||
const char *root,
|
|
||||||
char **ret,
|
|
||||||
sd_json_variant **ret_package_metadata,
|
|
||||||
sd_json_variant **ret_dlopen_metadata) {
|
|
||||||
|
|
||||||
const Dwfl_Callbacks callbacks = {
|
const Dwfl_Callbacks callbacks = {
|
||||||
.find_elf = sym_dwfl_build_id_find_elf,
|
.find_elf = sym_dwfl_build_id_find_elf,
|
||||||
@ -629,11 +608,10 @@ static int parse_core(
|
|||||||
.find_debuginfo = sym_dwfl_standard_find_debuginfo,
|
.find_debuginfo = sym_dwfl_standard_find_debuginfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *package_metadata = NULL, *dlopen_metadata = NULL;
|
_cleanup_(sd_json_variant_unrefp) sd_json_variant *package_metadata = NULL;
|
||||||
_cleanup_set_free_ Set *modules = NULL;
|
_cleanup_set_free_ Set *modules = NULL;
|
||||||
_cleanup_(stack_context_done) StackContext c = {
|
_cleanup_(stack_context_done) StackContext c = {
|
||||||
.package_metadata = &package_metadata,
|
.package_metadata = &package_metadata,
|
||||||
.dlopen_metadata = ret_dlopen_metadata ? &dlopen_metadata : NULL,
|
|
||||||
.modules = &modules,
|
.modules = &modules,
|
||||||
};
|
};
|
||||||
int r;
|
int r;
|
||||||
@ -689,24 +667,15 @@ static int parse_core(
|
|||||||
|
|
||||||
if (ret_package_metadata)
|
if (ret_package_metadata)
|
||||||
*ret_package_metadata = TAKE_PTR(package_metadata);
|
*ret_package_metadata = TAKE_PTR(package_metadata);
|
||||||
if (ret_dlopen_metadata)
|
|
||||||
*ret_dlopen_metadata = TAKE_PTR(dlopen_metadata);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_elf(
|
static int parse_elf(int fd, const char *executable, const char *root, char **ret, sd_json_variant **ret_package_metadata) {
|
||||||
int fd,
|
_cleanup_(sd_json_variant_unrefp) sd_json_variant *package_metadata = NULL, *elf_metadata = NULL;
|
||||||
const char *executable,
|
|
||||||
const char *root,
|
|
||||||
char **ret,
|
|
||||||
sd_json_variant **ret_package_metadata,
|
|
||||||
sd_json_variant **ret_dlopen_metadata) {
|
|
||||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *package_metadata = NULL, *dlopen_metadata = NULL, *elf_metadata = NULL;
|
|
||||||
_cleanup_set_free_ Set *modules = NULL;
|
_cleanup_set_free_ Set *modules = NULL;
|
||||||
_cleanup_(stack_context_done) StackContext c = {
|
_cleanup_(stack_context_done) StackContext c = {
|
||||||
.package_metadata = &package_metadata,
|
.package_metadata = &package_metadata,
|
||||||
.dlopen_metadata = ret_dlopen_metadata ? &dlopen_metadata : NULL,
|
|
||||||
.modules = &modules,
|
.modules = &modules,
|
||||||
};
|
};
|
||||||
const char *elf_type;
|
const char *elf_type;
|
||||||
@ -733,7 +702,7 @@ static int parse_elf(
|
|||||||
if (elf_header.e_type == ET_CORE) {
|
if (elf_header.e_type == ET_CORE) {
|
||||||
_cleanup_free_ char *out = NULL;
|
_cleanup_free_ char *out = NULL;
|
||||||
|
|
||||||
r = parse_core(fd, root, ret ? &out : NULL, &package_metadata, &dlopen_metadata);
|
r = parse_core(fd, root, ret ? &out : NULL, &package_metadata);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_warning_errno(r, "Failed to inspect core file: %m");
|
return log_warning_errno(r, "Failed to inspect core file: %m");
|
||||||
|
|
||||||
@ -750,7 +719,7 @@ static int parse_elf(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_warning_errno(r, "Failed to parse build-id of ELF file: %m");
|
return log_warning_errno(r, "Failed to parse build-id of ELF file: %m");
|
||||||
|
|
||||||
r = parse_metadata(e, id_json, c.elf, &interpreter_found, &c);
|
r = parse_package_metadata(e, id_json, c.elf, &interpreter_found, &c);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_warning_errno(r, "Failed to parse package metadata of ELF file: %m");
|
return log_warning_errno(r, "Failed to parse package metadata of ELF file: %m");
|
||||||
|
|
||||||
@ -800,28 +769,18 @@ static int parse_elf(
|
|||||||
|
|
||||||
if (ret_package_metadata)
|
if (ret_package_metadata)
|
||||||
*ret_package_metadata = TAKE_PTR(elf_metadata);
|
*ret_package_metadata = TAKE_PTR(elf_metadata);
|
||||||
if (ret_dlopen_metadata)
|
|
||||||
*ret_dlopen_metadata = TAKE_PTR(dlopen_metadata);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int parse_elf_object(
|
int parse_elf_object(int fd, const char *executable, const char *root, bool fork_disable_dump, char **ret, sd_json_variant **ret_package_metadata) {
|
||||||
int fd,
|
|
||||||
const char *executable,
|
|
||||||
const char *root,
|
|
||||||
bool fork_disable_dump,
|
|
||||||
char **ret,
|
|
||||||
sd_json_variant **ret_package_metadata,
|
|
||||||
sd_json_variant **ret_dlopen_metadata) {
|
|
||||||
#if HAVE_ELFUTILS
|
#if HAVE_ELFUTILS
|
||||||
_cleanup_close_pair_ int error_pipe[2] = EBADF_PAIR,
|
_cleanup_close_pair_ int error_pipe[2] = EBADF_PAIR,
|
||||||
return_pipe[2] = EBADF_PAIR,
|
return_pipe[2] = EBADF_PAIR,
|
||||||
package_metadata_pipe[2] = EBADF_PAIR,
|
json_pipe[2] = EBADF_PAIR;
|
||||||
dlopen_metadata_pipe[2] = EBADF_PAIR;
|
_cleanup_(sd_json_variant_unrefp) sd_json_variant *package_metadata = NULL;
|
||||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *package_metadata = NULL, *dlopen_metadata = NULL;
|
|
||||||
_cleanup_free_ char *buf = NULL;
|
_cleanup_free_ char *buf = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -846,13 +805,7 @@ int parse_elf_object(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ret_package_metadata) {
|
if (ret_package_metadata) {
|
||||||
r = RET_NERRNO(pipe2(package_metadata_pipe, O_CLOEXEC|O_NONBLOCK));
|
r = RET_NERRNO(pipe2(json_pipe, O_CLOEXEC|O_NONBLOCK));
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret_dlopen_metadata) {
|
|
||||||
r = RET_NERRNO(pipe2(dlopen_metadata_pipe, O_CLOEXEC|O_NONBLOCK));
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -865,8 +818,8 @@ int parse_elf_object(
|
|||||||
* the file descriptor and writing into these four pipes. */
|
* the file descriptor and writing into these four pipes. */
|
||||||
r = safe_fork_full("(sd-parse-elf)",
|
r = safe_fork_full("(sd-parse-elf)",
|
||||||
NULL,
|
NULL,
|
||||||
(int[]){ fd, error_pipe[1], return_pipe[1], package_metadata_pipe[1], dlopen_metadata_pipe[1] },
|
(int[]){ fd, error_pipe[1], return_pipe[1], json_pipe[1] },
|
||||||
5,
|
4,
|
||||||
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_NEW_USERNS|FORK_WAIT|FORK_REOPEN_LOG,
|
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_NEW_USERNS|FORK_WAIT|FORK_REOPEN_LOG,
|
||||||
NULL);
|
NULL);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
@ -893,13 +846,7 @@ int parse_elf_object(
|
|||||||
report_errno_and_exit(error_pipe[1], r);
|
report_errno_and_exit(error_pipe[1], r);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = parse_elf(
|
r = parse_elf(fd, executable, root, ret ? &buf : NULL, ret_package_metadata ? &package_metadata : NULL);
|
||||||
fd,
|
|
||||||
executable,
|
|
||||||
root,
|
|
||||||
ret ? &buf : NULL,
|
|
||||||
ret_package_metadata ? &package_metadata : NULL,
|
|
||||||
ret_dlopen_metadata ? &dlopen_metadata : NULL);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
report_errno_and_exit(error_pipe[1], r);
|
report_errno_and_exit(error_pipe[1], r);
|
||||||
|
|
||||||
@ -932,9 +879,9 @@ int parse_elf_object(
|
|||||||
|
|
||||||
/* Bump the space for the returned string. We don't know how much space we'll need in
|
/* Bump the space for the returned string. We don't know how much space we'll need in
|
||||||
* advance, so we'll just try to write as much as possible and maybe fail later. */
|
* advance, so we'll just try to write as much as possible and maybe fail later. */
|
||||||
(void) fcntl(package_metadata_pipe[1], F_SETPIPE_SZ, COREDUMP_PIPE_MAX);
|
(void) fcntl(json_pipe[1], F_SETPIPE_SZ, COREDUMP_PIPE_MAX);
|
||||||
|
|
||||||
json_out = take_fdopen(&package_metadata_pipe[1], "w");
|
json_out = take_fdopen(&json_pipe[1], "w");
|
||||||
if (!json_out)
|
if (!json_out)
|
||||||
report_errno_and_exit(error_pipe[1], -errno);
|
report_errno_and_exit(error_pipe[1], -errno);
|
||||||
|
|
||||||
@ -943,29 +890,12 @@ int parse_elf_object(
|
|||||||
log_warning_errno(r, "Failed to write JSON package metadata, ignoring: %m");
|
log_warning_errno(r, "Failed to write JSON package metadata, ignoring: %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dlopen_metadata) {
|
|
||||||
_cleanup_fclose_ FILE *json_out = NULL;
|
|
||||||
|
|
||||||
/* Bump the space for the returned string. We don't know how much space we'll need in
|
|
||||||
* advance, so we'll just try to write as much as possible and maybe fail later. */
|
|
||||||
(void) fcntl(dlopen_metadata_pipe[1], F_SETPIPE_SZ, COREDUMP_PIPE_MAX);
|
|
||||||
|
|
||||||
json_out = take_fdopen(&dlopen_metadata_pipe[1], "w");
|
|
||||||
if (!json_out)
|
|
||||||
report_errno_and_exit(error_pipe[1], -errno);
|
|
||||||
|
|
||||||
r = sd_json_variant_dump(dlopen_metadata, SD_JSON_FORMAT_FLUSH, json_out, NULL);
|
|
||||||
if (r < 0)
|
|
||||||
log_warning_errno(r, "Failed to write JSON package metadata, ignoring: %m");
|
|
||||||
}
|
|
||||||
|
|
||||||
_exit(EXIT_SUCCESS);
|
_exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
error_pipe[1] = safe_close(error_pipe[1]);
|
error_pipe[1] = safe_close(error_pipe[1]);
|
||||||
return_pipe[1] = safe_close(return_pipe[1]);
|
return_pipe[1] = safe_close(return_pipe[1]);
|
||||||
package_metadata_pipe[1] = safe_close(package_metadata_pipe[1]);
|
json_pipe[1] = safe_close(json_pipe[1]);
|
||||||
dlopen_metadata_pipe[1] = safe_close(dlopen_metadata_pipe[1]);
|
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
_cleanup_fclose_ FILE *in = NULL;
|
_cleanup_fclose_ FILE *in = NULL;
|
||||||
@ -982,33 +912,19 @@ int parse_elf_object(
|
|||||||
if (ret_package_metadata) {
|
if (ret_package_metadata) {
|
||||||
_cleanup_fclose_ FILE *json_in = NULL;
|
_cleanup_fclose_ FILE *json_in = NULL;
|
||||||
|
|
||||||
json_in = take_fdopen(&package_metadata_pipe[0], "r");
|
json_in = take_fdopen(&json_pipe[0], "r");
|
||||||
if (!json_in)
|
if (!json_in)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
r = sd_json_parse_file(json_in, NULL, 0, &package_metadata, NULL, NULL);
|
r = sd_json_parse_file(json_in, NULL, 0, &package_metadata, NULL, NULL);
|
||||||
if (r < 0 && r != -ENODATA) /* ENODATA: json was empty, so we got nothing, but that's ok */
|
if (r < 0 && r != -ENODATA) /* ENODATA: json was empty, so we got nothing, but that's ok */
|
||||||
log_warning_errno(r, "Failed to read or parse package metadata, ignoring: %m");
|
log_warning_errno(r, "Failed to read or parse json metadata, ignoring: %m");
|
||||||
}
|
|
||||||
|
|
||||||
if (ret_dlopen_metadata) {
|
|
||||||
_cleanup_fclose_ FILE *json_in = NULL;
|
|
||||||
|
|
||||||
json_in = take_fdopen(&dlopen_metadata_pipe[0], "r");
|
|
||||||
if (!json_in)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
r = sd_json_parse_file(json_in, NULL, 0, &dlopen_metadata, NULL, NULL);
|
|
||||||
if (r < 0 && r != -ENODATA) /* ENODATA: json was empty, so we got nothing, but that's ok */
|
|
||||||
log_warning_errno(r, "Failed to read or parse dlopen metadata, ignoring: %m");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
*ret = TAKE_PTR(buf);
|
*ret = TAKE_PTR(buf);
|
||||||
if (ret_package_metadata)
|
if (ret_package_metadata)
|
||||||
*ret_package_metadata = TAKE_PTR(package_metadata);
|
*ret_package_metadata = TAKE_PTR(package_metadata);
|
||||||
if (ret_dlopen_metadata)
|
|
||||||
*ret_dlopen_metadata = TAKE_PTR(dlopen_metadata);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
|
|||||||
@ -9,11 +9,4 @@ int dlopen_elf(void);
|
|||||||
/* Parse an ELF object in a forked process, so that errors while iterating over
|
/* Parse an ELF object in a forked process, so that errors while iterating over
|
||||||
* untrusted and potentially malicious data do not propagate to the main caller's process.
|
* untrusted and potentially malicious data do not propagate to the main caller's process.
|
||||||
* If fork_disable_dump, the child process will not dump core if it crashes. */
|
* If fork_disable_dump, the child process will not dump core if it crashes. */
|
||||||
int parse_elf_object(
|
int parse_elf_object(int fd, const char *executable, const char *root, bool fork_disable_dump, char **ret, sd_json_variant **ret_package_metadata);
|
||||||
int fd,
|
|
||||||
const char *executable,
|
|
||||||
const char *root,
|
|
||||||
bool fork_disable_dump,
|
|
||||||
char **ret,
|
|
||||||
sd_json_variant **ret_package_metadata,
|
|
||||||
sd_json_variant **ret_dlopen_metadata);
|
|
||||||
|
|||||||
@ -21,20 +21,20 @@
|
|||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
#include "tmpfile-util.h"
|
|
||||||
#include "uid-range.h"
|
#include "uid-range.h"
|
||||||
#include "user-util.h"
|
#include "user-util.h"
|
||||||
#include "virt.h"
|
#include "virt.h"
|
||||||
|
|
||||||
TEST(namespace_cleanup_tmpdir) {
|
TEST(namespace_cleanup_tmpdir) {
|
||||||
{
|
{
|
||||||
_cleanup_(namespace_cleanup_tmpdirp) char *dir = NULL;
|
_cleanup_(namespace_cleanup_tmpdirp) char *dir;
|
||||||
ASSERT_NOT_NULL(dir = strdup(RUN_SYSTEMD_EMPTY));
|
assert_se(dir = strdup(RUN_SYSTEMD_EMPTY));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
_cleanup_(namespace_cleanup_tmpdirp) char *dir = NULL;
|
_cleanup_(namespace_cleanup_tmpdirp) char *dir;
|
||||||
ASSERT_OK(mkdtemp_malloc("/tmp/systemd-test-namespace.XXXXXX", &dir));
|
assert_se(dir = strdup("/tmp/systemd-test-namespace.XXXXXX"));
|
||||||
|
assert_se(mkdtemp(dir));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,34 +43,34 @@ static void test_tmpdir_one(const char *id, const char *A, const char *B) {
|
|||||||
struct stat x, y;
|
struct stat x, y;
|
||||||
char *c, *d;
|
char *c, *d;
|
||||||
|
|
||||||
ASSERT_OK_ZERO(setup_tmp_dirs(id, &a, &b));
|
assert_se(setup_tmp_dirs(id, &a, &b) == 0);
|
||||||
|
|
||||||
ASSERT_OK_ERRNO(stat(a, &x));
|
assert_se(stat(a, &x) >= 0);
|
||||||
ASSERT_OK_ERRNO(stat(b, &y));
|
assert_se(stat(b, &y) >= 0);
|
||||||
|
|
||||||
ASSERT_TRUE(S_ISDIR(x.st_mode));
|
assert_se(S_ISDIR(x.st_mode));
|
||||||
ASSERT_TRUE(S_ISDIR(y.st_mode));
|
assert_se(S_ISDIR(y.st_mode));
|
||||||
|
|
||||||
if (!streq(a, RUN_SYSTEMD_EMPTY)) {
|
if (!streq(a, RUN_SYSTEMD_EMPTY)) {
|
||||||
ASSERT_TRUE(startswith(a, A));
|
assert_se(startswith(a, A));
|
||||||
ASSERT_EQ((x.st_mode & 01777), 0700U);
|
assert_se((x.st_mode & 01777) == 0700);
|
||||||
ASSERT_NOT_NULL(c = strjoina(a, "/tmp"));
|
c = strjoina(a, "/tmp");
|
||||||
ASSERT_OK_ERRNO(stat(c, &x));
|
assert_se(stat(c, &x) >= 0);
|
||||||
ASSERT_TRUE(S_ISDIR(x.st_mode));
|
assert_se(S_ISDIR(x.st_mode));
|
||||||
ASSERT_TRUE(FLAGS_SET(x.st_mode, 01777));
|
assert_se(FLAGS_SET(x.st_mode, 01777));
|
||||||
ASSERT_OK_ERRNO(rmdir(c));
|
assert_se(rmdir(c) >= 0);
|
||||||
ASSERT_OK_ERRNO(rmdir(a));
|
assert_se(rmdir(a) >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!streq(b, RUN_SYSTEMD_EMPTY)) {
|
if (!streq(b, RUN_SYSTEMD_EMPTY)) {
|
||||||
ASSERT_TRUE(startswith(b, B));
|
assert_se(startswith(b, B));
|
||||||
ASSERT_EQ((y.st_mode & 01777), 0700U);
|
assert_se((y.st_mode & 01777) == 0700);
|
||||||
ASSERT_NOT_NULL(d = strjoina(b, "/tmp"));
|
d = strjoina(b, "/tmp");
|
||||||
ASSERT_OK_ERRNO(stat(d, &y));
|
assert_se(stat(d, &y) >= 0);
|
||||||
ASSERT_TRUE(S_ISDIR(y.st_mode));
|
assert_se(S_ISDIR(y.st_mode));
|
||||||
ASSERT_TRUE(FLAGS_SET(y.st_mode, 01777));
|
assert_se(FLAGS_SET(y.st_mode, 01777));
|
||||||
ASSERT_OK_ERRNO(rmdir(d));
|
assert_se(rmdir(d) >= 0);
|
||||||
ASSERT_OK_ERRNO(rmdir(b));
|
assert_se(rmdir(b) >= 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,15 +78,18 @@ TEST(tmpdir) {
|
|||||||
_cleanup_free_ char *x = NULL, *y = NULL, *z = NULL, *zz = NULL;
|
_cleanup_free_ char *x = NULL, *y = NULL, *z = NULL, *zz = NULL;
|
||||||
sd_id128_t bid;
|
sd_id128_t bid;
|
||||||
|
|
||||||
ASSERT_OK(sd_id128_get_boot(&bid));
|
assert_se(sd_id128_get_boot(&bid) >= 0);
|
||||||
|
|
||||||
ASSERT_NOT_NULL(x = strjoin("/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-abcd.service-"));
|
x = strjoin("/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-abcd.service-");
|
||||||
ASSERT_NOT_NULL(y = strjoin("/var/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-abcd.service-"));
|
y = strjoin("/var/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-abcd.service-");
|
||||||
|
assert_se(x && y);
|
||||||
|
|
||||||
test_tmpdir_one("abcd.service", x, y);
|
test_tmpdir_one("abcd.service", x, y);
|
||||||
|
|
||||||
ASSERT_NOT_NULL(z = strjoin("/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device-"));
|
z = strjoin("/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device-");
|
||||||
ASSERT_NOT_NULL(zz = strjoin("/var/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device-"));
|
zz = strjoin("/var/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device-");
|
||||||
|
|
||||||
|
assert_se(z && zz);
|
||||||
|
|
||||||
test_tmpdir_one("sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device", z, zz);
|
test_tmpdir_one("sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device", z, zz);
|
||||||
}
|
}
|
||||||
@ -103,54 +106,54 @@ static void test_shareable_ns(unsigned long nsflag) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_OK_ERRNO(socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, s));
|
assert_se(socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, s) >= 0);
|
||||||
|
|
||||||
pid1 = fork();
|
pid1 = fork();
|
||||||
ASSERT_OK_ERRNO(pid1);
|
assert_se(pid1 >= 0);
|
||||||
|
|
||||||
if (pid1 == 0) {
|
if (pid1 == 0) {
|
||||||
r = setup_shareable_ns(s, nsflag);
|
r = setup_shareable_ns(s, nsflag);
|
||||||
if (!ERRNO_IS_PRIVILEGE(r))
|
assert_se(r >= 0 || ERRNO_IS_NEG_PRIVILEGE(r));
|
||||||
ASSERT_OK(r);
|
|
||||||
_exit(r >= 0 ? r : EX_NOPERM);
|
_exit(r >= 0 ? r : EX_NOPERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid2 = fork();
|
pid2 = fork();
|
||||||
ASSERT_OK_ERRNO(pid2);
|
assert_se(pid2 >= 0);
|
||||||
|
|
||||||
if (pid2 == 0) {
|
if (pid2 == 0) {
|
||||||
r = setup_shareable_ns(s, nsflag);
|
r = setup_shareable_ns(s, nsflag);
|
||||||
if (!ERRNO_IS_PRIVILEGE(r))
|
assert_se(r >= 0 || ERRNO_IS_NEG_PRIVILEGE(r));
|
||||||
ASSERT_OK(r);
|
|
||||||
_exit(r >= 0 ? r : EX_NOPERM);
|
_exit(r >= 0 ? r : EX_NOPERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid3 = fork();
|
pid3 = fork();
|
||||||
ASSERT_OK_ERRNO(pid3);
|
assert_se(pid3 >= 0);
|
||||||
|
|
||||||
if (pid3 == 0) {
|
if (pid3 == 0) {
|
||||||
r = setup_shareable_ns(s, nsflag);
|
r = setup_shareable_ns(s, nsflag);
|
||||||
if (!ERRNO_IS_PRIVILEGE(r))
|
assert_se(r >= 0 || ERRNO_IS_NEG_PRIVILEGE(r));
|
||||||
ASSERT_OK(r);
|
|
||||||
_exit(r >= 0 ? r : EX_NOPERM);
|
_exit(r >= 0 ? r : EX_NOPERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_OK(wait_for_terminate(pid1, &si));
|
r = wait_for_terminate(pid1, &si);
|
||||||
ASSERT_EQ(si.si_code, CLD_EXITED);
|
assert_se(r >= 0);
|
||||||
|
assert_se(si.si_code == CLD_EXITED);
|
||||||
if (si.si_status == EX_NOPERM)
|
if (si.si_status == EX_NOPERM)
|
||||||
permission_denied = true;
|
permission_denied = true;
|
||||||
else
|
else
|
||||||
n += si.si_status;
|
n += si.si_status;
|
||||||
|
|
||||||
ASSERT_OK(wait_for_terminate(pid2, &si));
|
r = wait_for_terminate(pid2, &si);
|
||||||
ASSERT_EQ(si.si_code, CLD_EXITED);
|
assert_se(r >= 0);
|
||||||
|
assert_se(si.si_code == CLD_EXITED);
|
||||||
if (si.si_status == EX_NOPERM)
|
if (si.si_status == EX_NOPERM)
|
||||||
permission_denied = true;
|
permission_denied = true;
|
||||||
else
|
else
|
||||||
n += si.si_status;
|
n += si.si_status;
|
||||||
|
|
||||||
ASSERT_OK(wait_for_terminate(pid3, &si));
|
r = wait_for_terminate(pid3, &si);
|
||||||
ASSERT_EQ(si.si_code, CLD_EXITED);
|
assert_se(r >= 0);
|
||||||
|
assert_se(si.si_code == CLD_EXITED);
|
||||||
if (si.si_status == EX_NOPERM)
|
if (si.si_status == EX_NOPERM)
|
||||||
permission_denied = true;
|
permission_denied = true;
|
||||||
else
|
else
|
||||||
@ -161,7 +164,7 @@ static void test_shareable_ns(unsigned long nsflag) {
|
|||||||
if (permission_denied)
|
if (permission_denied)
|
||||||
return (void) log_tests_skipped("insufficient privileges");
|
return (void) log_tests_skipped("insufficient privileges");
|
||||||
|
|
||||||
ASSERT_EQ(n, 1);
|
assert_se(n == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(netns) {
|
TEST(netns) {
|
||||||
@ -203,6 +206,7 @@ TEST(protect_kernel_logs) {
|
|||||||
.protect_kernel_logs = true,
|
.protect_kernel_logs = true,
|
||||||
};
|
};
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
int r;
|
||||||
|
|
||||||
if (geteuid() > 0) {
|
if (geteuid() > 0) {
|
||||||
(void) log_tests_skipped("not root");
|
(void) log_tests_skipped("not root");
|
||||||
@ -216,30 +220,33 @@ TEST(protect_kernel_logs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
ASSERT_OK_ERRNO(pid);
|
assert_se(pid >= 0);
|
||||||
|
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
_cleanup_close_ int fd = -EBADF;
|
_cleanup_close_ int fd = -EBADF;
|
||||||
|
|
||||||
ASSERT_OK_ERRNO(fd = open("/dev/kmsg", O_RDONLY | O_CLOEXEC));
|
fd = open("/dev/kmsg", O_RDONLY | O_CLOEXEC);
|
||||||
|
assert_se(fd > 0);
|
||||||
|
|
||||||
ASSERT_OK_ZERO(setup_namespace(&p, NULL));
|
r = setup_namespace(&p, NULL);
|
||||||
|
assert_se(r == 0);
|
||||||
|
|
||||||
ASSERT_OK_ERRNO(setresuid(UID_NOBODY, UID_NOBODY, UID_NOBODY));
|
assert_se(setresuid(UID_NOBODY, UID_NOBODY, UID_NOBODY) >= 0);
|
||||||
ASSERT_ERROR_ERRNO(open("/dev/kmsg", O_RDONLY | O_CLOEXEC), EACCES);
|
assert_se(open("/dev/kmsg", O_RDONLY | O_CLOEXEC) < 0);
|
||||||
|
assert_se(errno == EACCES);
|
||||||
|
|
||||||
_exit(EXIT_SUCCESS);
|
_exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_OK_EQ(wait_for_terminate_and_check("ns-kernellogs", pid, WAIT_LOG), EXIT_SUCCESS);
|
assert_se(wait_for_terminate_and_check("ns-kernellogs", pid, WAIT_LOG) == EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(idmapping_supported) {
|
TEST(idmapping_supported) {
|
||||||
ASSERT_OK(is_idmapping_supported("/run"));
|
assert_se(is_idmapping_supported("/run") >= 0);
|
||||||
ASSERT_OK(is_idmapping_supported("/var/lib"));
|
assert_se(is_idmapping_supported("/var/lib") >= 0);
|
||||||
ASSERT_OK(is_idmapping_supported("/var/cache"));
|
assert_se(is_idmapping_supported("/var/cache") >= 0);
|
||||||
ASSERT_OK(is_idmapping_supported("/var/log"));
|
assert_se(is_idmapping_supported("/var/log") >= 0);
|
||||||
ASSERT_OK(is_idmapping_supported("/etc"));
|
assert_se(is_idmapping_supported("/etc") >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(namespace_is_init) {
|
TEST(namespace_is_init) {
|
||||||
|
|||||||
@ -18,7 +18,7 @@ systemd-analyze time || :
|
|||||||
systemd-analyze critical-chain || :
|
systemd-analyze critical-chain || :
|
||||||
# blame
|
# blame
|
||||||
systemd-analyze blame
|
systemd-analyze blame
|
||||||
systemd-run --wait --user --pipe -M testuser@.host systemd-analyze blame --no-pager
|
systemd-run --wait --user --pipe -M testuser@.host systemd-analyze blame
|
||||||
(! systemd-analyze blame --global)
|
(! systemd-analyze blame --global)
|
||||||
# plot
|
# plot
|
||||||
systemd-analyze plot >/dev/null || :
|
systemd-analyze plot >/dev/null || :
|
||||||
@ -1006,16 +1006,7 @@ systemd-analyze security --threshold=25 --offline=true \
|
|||||||
rm /tmp/img/usr/lib/systemd/system/testfile.service
|
rm /tmp/img/usr/lib/systemd/system/testfile.service
|
||||||
|
|
||||||
if systemd-analyze --version | grep -q -F "+ELFUTILS"; then
|
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"'
|
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
|
fi
|
||||||
|
|
||||||
systemd-analyze --threshold=90 security systemd-journald.service
|
systemd-analyze --threshold=90 security systemd-journald.service
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user