mirror of
https://github.com/systemd/systemd
synced 2025-11-18 00:04:46 +01:00
Compare commits
8 Commits
f54d72c2b6
...
b5d63191ca
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5d63191ca | ||
|
|
097536a49c | ||
|
|
92ea9584c6 | ||
|
|
9851382c12 | ||
|
|
44ca5b8002 | ||
|
|
0fe29d0672 | ||
|
|
da30f59f60 | ||
|
|
004b7f1f7e |
@ -611,6 +611,10 @@ 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,6 +915,16 @@ 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>
|
||||||
|
|
||||||
|
|||||||
72
src/analyze/analyze-dlopen-metadata.c
Normal file
72
src/analyze/analyze-dlopen-metadata.c
Normal file
@ -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;
|
||||||
|
}
|
||||||
4
src/analyze/analyze-dlopen-metadata.h
Normal file
4
src/analyze/analyze-dlopen-metadata.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
int verb_dlopen_metadata(int argc, char *argv[], void *userdata);
|
||||||
@ -27,7 +27,14 @@ 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(fd, abspath, arg_root, /* fork_disable_dump= */false, &stacktrace, &package_metadata);
|
r = parse_elf_object(
|
||||||
|
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,6 +22,7 @@
|
|||||||
#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"
|
||||||
@ -798,6 +799,7 @@ 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,6 +10,7 @@ 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,7 +689,8 @@ 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,8 +287,6 @@ 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;
|
||||||
@ -296,40 +294,37 @@ 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("userName", SD_JSON_BUILD_STRING(h->user_name)),
|
SD_JSON_BUILD_PAIR_STRING("userName", h->user_name),
|
||||||
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(p.group_name)));
|
SD_JSON_BUILD_PAIR_STRING("groupName", p.group_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
STRV_FOREACH(i, h->record->member_of) {
|
STRV_FOREACH(i, h->record->member_of) {
|
||||||
if (last) {
|
|
||||||
r = sd_varlink_notifybo(
|
r = sd_varlink_notifybo(
|
||||||
link,
|
link,
|
||||||
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(h->user_name)),
|
SD_JSON_BUILD_PAIR_STRING("userName", h->user_name),
|
||||||
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(last)));
|
SD_JSON_BUILD_PAIR_STRING("groupName", *i));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
last = *i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (last)
|
|
||||||
return sd_varlink_replybo(
|
return sd_varlink_replybo(
|
||||||
link,
|
link,
|
||||||
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(h->user_name)),
|
SD_JSON_BUILD_PAIR_STRING("userName", h->user_name),
|
||||||
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(last)));
|
SD_JSON_BUILD_PAIR_STRING("groupName", h->user_name));
|
||||||
|
|
||||||
} 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) {
|
||||||
@ -350,34 +345,37 @@ 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_user_name = NULL, *last_group_name = NULL;
|
const char *last = 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) {
|
||||||
|
r = sd_varlink_notifybo(
|
||||||
|
link,
|
||||||
|
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(last)),
|
||||||
|
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(last)));
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
if (last_user_name) {
|
last = NULL;
|
||||||
assert(last_group_name);
|
}
|
||||||
|
|
||||||
r = sd_varlink_notifybo(
|
r = sd_varlink_notifybo(
|
||||||
link,
|
link,
|
||||||
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(last_user_name)),
|
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(h->user_name)),
|
||||||
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(last_group_name)));
|
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(*j)));
|
||||||
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
last_user_name = h->user_name;
|
last = h->user_name;
|
||||||
last_group_name = *j;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last_user_name) {
|
if (last)
|
||||||
assert(last_group_name);
|
|
||||||
return sd_varlink_replybo(
|
return sd_varlink_replybo(
|
||||||
link,
|
link,
|
||||||
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(last_user_name)),
|
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(last)),
|
||||||
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(last_group_name)));
|
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(last)));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sd_varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
return sd_varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
|
||||||
|
|||||||
@ -377,6 +377,8 @@ 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,6 +20,7 @@
|
|||||||
#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"
|
||||||
@ -186,6 +187,7 @@ 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;
|
||||||
|
|
||||||
@ -352,8 +354,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_package_metadata(const char *name, sd_json_variant *id_json, Elf *elf, bool *ret_interpreter_found, StackContext *c) {
|
static int parse_metadata(const char *name, sd_json_variant *id_json, Elf *elf, bool *ret_interpreter_found, StackContext *c) {
|
||||||
bool interpreter_found = false;
|
bool package_metadata_found = false, interpreter_found = false;
|
||||||
size_t n_program_headers;
|
size_t n_program_headers;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -408,7 +410,7 @@ static int parse_package_metadata(const char *name, sd_json_variant *id_json, El
|
|||||||
|
|
||||||
/* 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 (note_header.n_type != ELF_PACKAGE_METADATA_ID)
|
if (!IN_SET(note_header.n_type, ELF_PACKAGE_METADATA_ID, ELF_NOTE_DLOPEN_TYPE))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
_cleanup_free_ char *payload_0suffixed = NULL;
|
_cleanup_free_ char *payload_0suffixed = NULL;
|
||||||
@ -430,6 +432,7 @@ static int parse_package_metadata(const char *name, sd_json_variant *id_json, El
|
|||||||
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) {
|
||||||
@ -453,23 +456,35 @@ static int parse_package_metadata(const char *name, sd_json_variant *id_json, El
|
|||||||
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* 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;
|
||||||
|
|
||||||
/* Didn't find package metadata for this module - that's ok, just go to the next. */
|
return c->dlopen_metadata ? 0 : package_metadata_found;
|
||||||
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. */
|
||||||
@ -535,7 +550,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_package_metadata(name, id_json, elf, NULL, c);
|
r = parse_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)
|
||||||
@ -590,7 +605,8 @@ 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)
|
||||||
@ -600,7 +616,12 @@ static int module_callback(Dwfl_Module *mod, void **userdata, const char *name,
|
|||||||
return DWARF_CB_OK;
|
return DWARF_CB_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_core(int fd, const char *root, char **ret, sd_json_variant **ret_package_metadata) {
|
static int parse_core(
|
||||||
|
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,
|
||||||
@ -608,10 +629,11 @@ static int parse_core(int fd, const char *root, char **ret, sd_json_variant **re
|
|||||||
.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;
|
_cleanup_(sd_json_variant_unrefp) sd_json_variant *package_metadata = NULL, *dlopen_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;
|
||||||
@ -667,15 +689,24 @@ static int parse_core(int fd, const char *root, char **ret, sd_json_variant **re
|
|||||||
|
|
||||||
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(int fd, const char *executable, const char *root, char **ret, sd_json_variant **ret_package_metadata) {
|
static int parse_elf(
|
||||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *package_metadata = NULL, *elf_metadata = NULL;
|
int fd,
|
||||||
|
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;
|
||||||
@ -702,7 +733,7 @@ static int parse_elf(int fd, const char *executable, const char *root, char **re
|
|||||||
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);
|
r = parse_core(fd, root, ret ? &out : NULL, &package_metadata, &dlopen_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");
|
||||||
|
|
||||||
@ -719,7 +750,7 @@ static int parse_elf(int fd, const char *executable, const char *root, char **re
|
|||||||
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_package_metadata(e, id_json, c.elf, &interpreter_found, &c);
|
r = parse_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");
|
||||||
|
|
||||||
@ -769,18 +800,28 @@ static int parse_elf(int fd, const char *executable, const char *root, char **re
|
|||||||
|
|
||||||
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 fd, const char *executable, const char *root, bool fork_disable_dump, char **ret, sd_json_variant **ret_package_metadata) {
|
int parse_elf_object(
|
||||||
|
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,
|
||||||
json_pipe[2] = EBADF_PAIR;
|
package_metadata_pipe[2] = EBADF_PAIR,
|
||||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *package_metadata = NULL;
|
dlopen_metadata_pipe[2] = EBADF_PAIR;
|
||||||
|
_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;
|
||||||
|
|
||||||
@ -805,7 +846,13 @@ int parse_elf_object(int fd, const char *executable, const char *root, bool fork
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ret_package_metadata) {
|
if (ret_package_metadata) {
|
||||||
r = RET_NERRNO(pipe2(json_pipe, O_CLOEXEC|O_NONBLOCK));
|
r = RET_NERRNO(pipe2(package_metadata_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;
|
||||||
}
|
}
|
||||||
@ -818,8 +865,8 @@ int parse_elf_object(int fd, const char *executable, const char *root, bool fork
|
|||||||
* 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], json_pipe[1] },
|
(int[]){ fd, error_pipe[1], return_pipe[1], package_metadata_pipe[1], dlopen_metadata_pipe[1] },
|
||||||
4,
|
5,
|
||||||
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) {
|
||||||
@ -846,7 +893,13 @@ int parse_elf_object(int fd, const char *executable, const char *root, bool fork
|
|||||||
report_errno_and_exit(error_pipe[1], r);
|
report_errno_and_exit(error_pipe[1], r);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = parse_elf(fd, executable, root, ret ? &buf : NULL, ret_package_metadata ? &package_metadata : NULL);
|
r = parse_elf(
|
||||||
|
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);
|
||||||
|
|
||||||
@ -879,9 +932,9 @@ int parse_elf_object(int fd, const char *executable, const char *root, bool fork
|
|||||||
|
|
||||||
/* 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(json_pipe[1], F_SETPIPE_SZ, COREDUMP_PIPE_MAX);
|
(void) fcntl(package_metadata_pipe[1], F_SETPIPE_SZ, COREDUMP_PIPE_MAX);
|
||||||
|
|
||||||
json_out = take_fdopen(&json_pipe[1], "w");
|
json_out = take_fdopen(&package_metadata_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);
|
||||||
|
|
||||||
@ -890,12 +943,29 @@ int parse_elf_object(int fd, const char *executable, const char *root, bool fork
|
|||||||
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]);
|
||||||
json_pipe[1] = safe_close(json_pipe[1]);
|
package_metadata_pipe[1] = safe_close(package_metadata_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;
|
||||||
@ -912,19 +982,33 @@ int parse_elf_object(int fd, const char *executable, const char *root, bool fork
|
|||||||
if (ret_package_metadata) {
|
if (ret_package_metadata) {
|
||||||
_cleanup_fclose_ FILE *json_in = NULL;
|
_cleanup_fclose_ FILE *json_in = NULL;
|
||||||
|
|
||||||
json_in = take_fdopen(&json_pipe[0], "r");
|
json_in = take_fdopen(&package_metadata_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 json metadata, ignoring: %m");
|
log_warning_errno(r, "Failed to read or parse package 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,4 +9,11 @@ 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 fd, const char *executable, const char *root, bool fork_disable_dump, char **ret, sd_json_variant **ret_package_metadata);
|
int parse_elf_object(
|
||||||
|
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;
|
_cleanup_(namespace_cleanup_tmpdirp) char *dir = NULL;
|
||||||
assert_se(dir = strdup(RUN_SYSTEMD_EMPTY));
|
ASSERT_NOT_NULL(dir = strdup(RUN_SYSTEMD_EMPTY));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
_cleanup_(namespace_cleanup_tmpdirp) char *dir;
|
_cleanup_(namespace_cleanup_tmpdirp) char *dir = NULL;
|
||||||
assert_se(dir = strdup("/tmp/systemd-test-namespace.XXXXXX"));
|
ASSERT_OK(mkdtemp_malloc("/tmp/systemd-test-namespace.XXXXXX", &dir));
|
||||||
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_se(setup_tmp_dirs(id, &a, &b) == 0);
|
ASSERT_OK_ZERO(setup_tmp_dirs(id, &a, &b));
|
||||||
|
|
||||||
assert_se(stat(a, &x) >= 0);
|
ASSERT_OK_ERRNO(stat(a, &x));
|
||||||
assert_se(stat(b, &y) >= 0);
|
ASSERT_OK_ERRNO(stat(b, &y));
|
||||||
|
|
||||||
assert_se(S_ISDIR(x.st_mode));
|
ASSERT_TRUE(S_ISDIR(x.st_mode));
|
||||||
assert_se(S_ISDIR(y.st_mode));
|
ASSERT_TRUE(S_ISDIR(y.st_mode));
|
||||||
|
|
||||||
if (!streq(a, RUN_SYSTEMD_EMPTY)) {
|
if (!streq(a, RUN_SYSTEMD_EMPTY)) {
|
||||||
assert_se(startswith(a, A));
|
ASSERT_TRUE(startswith(a, A));
|
||||||
assert_se((x.st_mode & 01777) == 0700);
|
ASSERT_EQ((x.st_mode & 01777), 0700U);
|
||||||
c = strjoina(a, "/tmp");
|
ASSERT_NOT_NULL(c = strjoina(a, "/tmp"));
|
||||||
assert_se(stat(c, &x) >= 0);
|
ASSERT_OK_ERRNO(stat(c, &x));
|
||||||
assert_se(S_ISDIR(x.st_mode));
|
ASSERT_TRUE(S_ISDIR(x.st_mode));
|
||||||
assert_se(FLAGS_SET(x.st_mode, 01777));
|
ASSERT_TRUE(FLAGS_SET(x.st_mode, 01777));
|
||||||
assert_se(rmdir(c) >= 0);
|
ASSERT_OK_ERRNO(rmdir(c));
|
||||||
assert_se(rmdir(a) >= 0);
|
ASSERT_OK_ERRNO(rmdir(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!streq(b, RUN_SYSTEMD_EMPTY)) {
|
if (!streq(b, RUN_SYSTEMD_EMPTY)) {
|
||||||
assert_se(startswith(b, B));
|
ASSERT_TRUE(startswith(b, B));
|
||||||
assert_se((y.st_mode & 01777) == 0700);
|
ASSERT_EQ((y.st_mode & 01777), 0700U);
|
||||||
d = strjoina(b, "/tmp");
|
ASSERT_NOT_NULL(d = strjoina(b, "/tmp"));
|
||||||
assert_se(stat(d, &y) >= 0);
|
ASSERT_OK_ERRNO(stat(d, &y));
|
||||||
assert_se(S_ISDIR(y.st_mode));
|
ASSERT_TRUE(S_ISDIR(y.st_mode));
|
||||||
assert_se(FLAGS_SET(y.st_mode, 01777));
|
ASSERT_TRUE(FLAGS_SET(y.st_mode, 01777));
|
||||||
assert_se(rmdir(d) >= 0);
|
ASSERT_OK_ERRNO(rmdir(d));
|
||||||
assert_se(rmdir(b) >= 0);
|
ASSERT_OK_ERRNO(rmdir(b));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,18 +78,15 @@ 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_se(sd_id128_get_boot(&bid) >= 0);
|
ASSERT_OK(sd_id128_get_boot(&bid));
|
||||||
|
|
||||||
x = strjoin("/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-abcd.service-");
|
ASSERT_NOT_NULL(x = strjoin("/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-abcd.service-"));
|
||||||
y = strjoin("/var/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-"));
|
||||||
assert_se(x && y);
|
|
||||||
|
|
||||||
test_tmpdir_one("abcd.service", x, y);
|
test_tmpdir_one("abcd.service", x, y);
|
||||||
|
|
||||||
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(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-"));
|
||||||
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_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-"));
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
@ -106,54 +103,54 @@ static void test_shareable_ns(unsigned long nsflag) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_se(socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, s) >= 0);
|
ASSERT_OK_ERRNO(socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, s));
|
||||||
|
|
||||||
pid1 = fork();
|
pid1 = fork();
|
||||||
assert_se(pid1 >= 0);
|
ASSERT_OK_ERRNO(pid1);
|
||||||
|
|
||||||
if (pid1 == 0) {
|
if (pid1 == 0) {
|
||||||
r = setup_shareable_ns(s, nsflag);
|
r = setup_shareable_ns(s, nsflag);
|
||||||
assert_se(r >= 0 || ERRNO_IS_NEG_PRIVILEGE(r));
|
if (!ERRNO_IS_PRIVILEGE(r))
|
||||||
|
ASSERT_OK(r);
|
||||||
_exit(r >= 0 ? r : EX_NOPERM);
|
_exit(r >= 0 ? r : EX_NOPERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid2 = fork();
|
pid2 = fork();
|
||||||
assert_se(pid2 >= 0);
|
ASSERT_OK_ERRNO(pid2);
|
||||||
|
|
||||||
if (pid2 == 0) {
|
if (pid2 == 0) {
|
||||||
r = setup_shareable_ns(s, nsflag);
|
r = setup_shareable_ns(s, nsflag);
|
||||||
assert_se(r >= 0 || ERRNO_IS_NEG_PRIVILEGE(r));
|
if (!ERRNO_IS_PRIVILEGE(r))
|
||||||
|
ASSERT_OK(r);
|
||||||
_exit(r >= 0 ? r : EX_NOPERM);
|
_exit(r >= 0 ? r : EX_NOPERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid3 = fork();
|
pid3 = fork();
|
||||||
assert_se(pid3 >= 0);
|
ASSERT_OK_ERRNO(pid3);
|
||||||
|
|
||||||
if (pid3 == 0) {
|
if (pid3 == 0) {
|
||||||
r = setup_shareable_ns(s, nsflag);
|
r = setup_shareable_ns(s, nsflag);
|
||||||
assert_se(r >= 0 || ERRNO_IS_NEG_PRIVILEGE(r));
|
if (!ERRNO_IS_PRIVILEGE(r))
|
||||||
|
ASSERT_OK(r);
|
||||||
_exit(r >= 0 ? r : EX_NOPERM);
|
_exit(r >= 0 ? r : EX_NOPERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = wait_for_terminate(pid1, &si);
|
ASSERT_OK(wait_for_terminate(pid1, &si));
|
||||||
assert_se(r >= 0);
|
ASSERT_EQ(si.si_code, CLD_EXITED);
|
||||||
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;
|
||||||
|
|
||||||
r = wait_for_terminate(pid2, &si);
|
ASSERT_OK(wait_for_terminate(pid2, &si));
|
||||||
assert_se(r >= 0);
|
ASSERT_EQ(si.si_code, CLD_EXITED);
|
||||||
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;
|
||||||
|
|
||||||
r = wait_for_terminate(pid3, &si);
|
ASSERT_OK(wait_for_terminate(pid3, &si));
|
||||||
assert_se(r >= 0);
|
ASSERT_EQ(si.si_code, CLD_EXITED);
|
||||||
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
|
||||||
@ -164,7 +161,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_se(n == 1);
|
ASSERT_EQ(n, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(netns) {
|
TEST(netns) {
|
||||||
@ -206,7 +203,6 @@ 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");
|
||||||
@ -220,33 +216,30 @@ TEST(protect_kernel_logs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
assert_se(pid >= 0);
|
ASSERT_OK_ERRNO(pid);
|
||||||
|
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
_cleanup_close_ int fd = -EBADF;
|
_cleanup_close_ int fd = -EBADF;
|
||||||
|
|
||||||
fd = open("/dev/kmsg", O_RDONLY | O_CLOEXEC);
|
ASSERT_OK_ERRNO(fd = open("/dev/kmsg", O_RDONLY | O_CLOEXEC));
|
||||||
assert_se(fd > 0);
|
|
||||||
|
|
||||||
r = setup_namespace(&p, NULL);
|
ASSERT_OK_ZERO(setup_namespace(&p, NULL));
|
||||||
assert_se(r == 0);
|
|
||||||
|
|
||||||
assert_se(setresuid(UID_NOBODY, UID_NOBODY, UID_NOBODY) >= 0);
|
ASSERT_OK_ERRNO(setresuid(UID_NOBODY, UID_NOBODY, UID_NOBODY));
|
||||||
assert_se(open("/dev/kmsg", O_RDONLY | O_CLOEXEC) < 0);
|
ASSERT_ERROR_ERRNO(open("/dev/kmsg", O_RDONLY | O_CLOEXEC), EACCES);
|
||||||
assert_se(errno == EACCES);
|
|
||||||
|
|
||||||
_exit(EXIT_SUCCESS);
|
_exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_se(wait_for_terminate_and_check("ns-kernellogs", pid, WAIT_LOG) == EXIT_SUCCESS);
|
ASSERT_OK_EQ(wait_for_terminate_and_check("ns-kernellogs", pid, WAIT_LOG), EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(idmapping_supported) {
|
TEST(idmapping_supported) {
|
||||||
assert_se(is_idmapping_supported("/run") >= 0);
|
ASSERT_OK(is_idmapping_supported("/run"));
|
||||||
assert_se(is_idmapping_supported("/var/lib") >= 0);
|
ASSERT_OK(is_idmapping_supported("/var/lib"));
|
||||||
assert_se(is_idmapping_supported("/var/cache") >= 0);
|
ASSERT_OK(is_idmapping_supported("/var/cache"));
|
||||||
assert_se(is_idmapping_supported("/var/log") >= 0);
|
ASSERT_OK(is_idmapping_supported("/var/log"));
|
||||||
assert_se(is_idmapping_supported("/etc") >= 0);
|
ASSERT_OK(is_idmapping_supported("/etc"));
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
systemd-run --wait --user --pipe -M testuser@.host systemd-analyze blame --no-pager
|
||||||
(! systemd-analyze blame --global)
|
(! systemd-analyze blame --global)
|
||||||
# plot
|
# plot
|
||||||
systemd-analyze plot >/dev/null || :
|
systemd-analyze plot >/dev/null || :
|
||||||
@ -1006,7 +1006,16 @@ 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