1
0
mirror of https://github.com/systemd/systemd synced 2025-11-17 15:54:45 +01:00

Compare commits

..

No commits in common. "b5d63191cabc4b60744d743c28bc2f9a2419e711" and "f54d72c2b6463d3ba6d418cb710db5fed80e8fc0" have entirely different histories.

14 changed files with 154 additions and 348 deletions

View File

@ -611,10 +611,6 @@ mouse:usb:v046dpc548:name:Logitech USB Receiver Mouse:*
mouse:bluetooth:v046dpb035:name:MX Master 3S B Mouse:*
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
mouse:usb:v046dp406f:name:Logitech MX Ergo:*
mouse:usb:v046dpc52b:name:Logitech Unifying Device. Wireless PID:406f:*

View File

@ -915,16 +915,6 @@ alias.service:7: Unknown key name 'MysteryKey' in section 'Service', ignoring.
</example>
</refsect2>
<refsect2>
<title><command>systemd-analyze dlopen-metadata <replaceable>FILE</replaceable></command></title>
<para>This command will load the specified file, and if it is an ELF object (executables,
libraries, core files, etc.) it will parse the embedded dlopen metadata, if any, and print
it in a table or json format. See the
<ulink url="https://systemd.io/ELF_DLOPEN_METADATA/">
dlopen() Metadata for ELF Files</ulink> document for more information.</para>
</refsect2>
<refsect2>
<title><command>systemd-analyze fdstore <replaceable>UNIT</replaceable>...</command></title>

View File

@ -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;
}

View File

@ -1,4 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
int verb_dlopen_metadata(int argc, char *argv[], void *userdata);

View File

@ -27,14 +27,7 @@ static int analyze_elf(char **filenames, sd_json_format_flags_t json_flags) {
if (fd < 0)
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,
/* ret_dlopen_metadata= */ NULL);
r = parse_elf_object(fd, abspath, arg_root, /* fork_disable_dump= */false, &stacktrace, &package_metadata);
if (r < 0)
return log_error_errno(r, "Parsing \"%s\" as ELF object failed: %m", abspath);

View File

@ -22,7 +22,6 @@
#include "analyze-compare-versions.h"
#include "analyze-condition.h"
#include "analyze-critical-chain.h"
#include "analyze-dlopen-metadata.h"
#include "analyze-dot.h"
#include "analyze-dump.h"
#include "analyze-exit-status.h"
@ -799,7 +798,6 @@ static int run(int argc, char *argv[]) {
{ "timespan", 2, VERB_ANY, 0, verb_timespan },
{ "security", VERB_ANY, VERB_ANY, 0, verb_security },
{ "inspect-elf", 2, VERB_ANY, 0, verb_elf_inspection },
{ "dlopen-metadata", 2, 2, 0, verb_dlopen_metadata },
{ "malloc", VERB_ANY, VERB_ANY, 0, verb_malloc },
{ "fdstore", 2, VERB_ANY, 0, verb_fdstore },
{ "image-policy", 2, 2, 0, verb_image_policy },

View File

@ -10,7 +10,6 @@ systemd_analyze_sources = files(
'analyze-compare-versions.c',
'analyze-condition.c',
'analyze-critical-chain.c',
'analyze-dlopen-metadata.c',
'analyze-dot.c',
'analyze-dump.c',
'analyze-exit-status.c',

View File

@ -689,8 +689,7 @@ int coredump_submit(
root,
/* fork_disable_dump= */ skip, /* avoid loops */
&stacktrace,
&json_metadata,
/* ret_dlopen_metadata= */ NULL);
&json_metadata);
}
}

View File

@ -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);
if (p.user_name) {
const char *last = NULL;
r = manager_get_home_by_name(m, p.user_name, &h);
if (r < 0)
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);
if (p.group_name) {
if (!strv_contains(h->record->member_of, p.group_name) &&
!user_record_matches_user_name(h->record, p.group_name))
if (!strv_contains(h->record->member_of, p.group_name))
return sd_varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
return sd_varlink_replybo(
link,
SD_JSON_BUILD_PAIR_STRING("userName", h->user_name),
SD_JSON_BUILD_PAIR_STRING("groupName", p.group_name));
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(h->user_name)),
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(p.group_name)));
}
STRV_FOREACH(i, h->record->member_of) {
r = sd_varlink_notifybo(
link,
SD_JSON_BUILD_PAIR_STRING("userName", h->user_name),
SD_JSON_BUILD_PAIR_STRING("groupName", *i));
if (r < 0)
return r;
if (last) {
r = sd_varlink_notifybo(
link,
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(h->user_name)),
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(last)));
if (r < 0)
return r;
}
last = *i;
}
return sd_varlink_replybo(
link,
SD_JSON_BUILD_PAIR_STRING("userName", h->user_name),
SD_JSON_BUILD_PAIR_STRING("groupName", h->user_name));
if (last)
return sd_varlink_replybo(
link,
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) {
const char *last = NULL;
HASHMAP_FOREACH(h, m->homes_by_uid) {
if (!strv_contains(h->record->member_of, p.group_name) &&
!user_record_matches_user_name(h->record, p.group_name))
if (!strv_contains(h->record->member_of, p.group_name))
continue;
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("groupName", SD_JSON_BUILD_STRING(p.group_name)));
} 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) {
if (last) {
if (last_user_name) {
assert(last_group_name);
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)));
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(last_user_name)),
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(last_group_name)));
if (r < 0)
return r;
last = NULL;
}
r = sd_varlink_notifybo(
link,
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_user_name = h->user_name;
last_group_name = *j;
}
last = h->user_name;
}
if (last)
if (last_user_name) {
assert(last_group_name);
return sd_varlink_replybo(
link,
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(last)),
SD_JSON_BUILD_PAIR("groupName", 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_group_name)));
}
}
return sd_varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);

View File

@ -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)) &&
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;
manager_set_ip_forwarding(link->manager, family);

View File

@ -20,7 +20,6 @@
#include "fileio.h"
#include "format-util.h"
#include "io-util.h"
#include "json-util.h"
#include "log.h"
#include "memstream-util.h"
#include "path-util.h"
@ -187,7 +186,6 @@ typedef struct StackContext {
unsigned n_thread;
unsigned n_frame;
sd_json_variant **package_metadata;
sd_json_variant **dlopen_metadata;
Set **modules;
} StackContext;
@ -354,8 +352,8 @@ static void report_module_metadata(StackContext *c, const char *name, sd_json_va
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) {
bool package_metadata_found = false, interpreter_found = false;
static int parse_package_metadata(const char *name, sd_json_variant *id_json, Elf *elf, bool *ret_interpreter_found, StackContext *c) {
bool interpreter_found = false;
size_t n_program_headers;
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
* 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;
_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));
}
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
* nicely together in the logs/metadata. */
if (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 we have a build-id, merge it in the same JSON object so that it appears all
* nicely together in the logs/metadata. */
if (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");
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. */
r = set_put_strdup(c->modules, name);
if (r < 0)
return log_error_errno(r, "set_put_strdup failed: %m");
if (!c->dlopen_metadata) {
if (ret_interpreter_found)
*ret_interpreter_found = interpreter_found;
if (ret_interpreter_found)
*ret_interpreter_found = interpreter_found;
return 1;
}
return 1;
}
}
if (ret_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. */
@ -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. */
elf = sym_dwfl_module_getelf(mod, &bias);
if (elf) {
r = parse_metadata(name, id_json, elf, NULL, c);
r = parse_package_metadata(name, id_json, elf, NULL, c);
if (r < 0)
return DWARF_CB_ABORT;
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);
if (!memelf)
continue;
r = parse_metadata(name, id_json, memelf, NULL, c);
r = parse_package_metadata(name, id_json, memelf, NULL, c);
if (r < 0)
return DWARF_CB_ABORT;
if (r > 0)
@ -616,12 +600,7 @@ static int module_callback(Dwfl_Module *mod, void **userdata, const char *name,
return DWARF_CB_OK;
}
static int parse_core(
int fd,
const char *root,
char **ret,
sd_json_variant **ret_package_metadata,
sd_json_variant **ret_dlopen_metadata) {
static int parse_core(int fd, const char *root, char **ret, sd_json_variant **ret_package_metadata) {
const Dwfl_Callbacks callbacks = {
.find_elf = sym_dwfl_build_id_find_elf,
@ -629,11 +608,10 @@ static int parse_core(
.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_(stack_context_done) StackContext c = {
.package_metadata = &package_metadata,
.dlopen_metadata = ret_dlopen_metadata ? &dlopen_metadata : NULL,
.modules = &modules,
};
int r;
@ -689,24 +667,15 @@ static int parse_core(
if (ret_package_metadata)
*ret_package_metadata = TAKE_PTR(package_metadata);
if (ret_dlopen_metadata)
*ret_dlopen_metadata = TAKE_PTR(dlopen_metadata);
return 0;
}
static int parse_elf(
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;
static int parse_elf(int fd, const char *executable, const char *root, char **ret, sd_json_variant **ret_package_metadata) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *package_metadata = NULL, *elf_metadata = NULL;
_cleanup_set_free_ Set *modules = NULL;
_cleanup_(stack_context_done) StackContext c = {
.package_metadata = &package_metadata,
.dlopen_metadata = ret_dlopen_metadata ? &dlopen_metadata : NULL,
.modules = &modules,
};
const char *elf_type;
@ -733,7 +702,7 @@ static int parse_elf(
if (elf_header.e_type == ET_CORE) {
_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)
return log_warning_errno(r, "Failed to inspect core file: %m");
@ -750,7 +719,7 @@ static int parse_elf(
if (r < 0)
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)
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)
*ret_package_metadata = TAKE_PTR(elf_metadata);
if (ret_dlopen_metadata)
*ret_dlopen_metadata = TAKE_PTR(dlopen_metadata);
return 0;
}
#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,
sd_json_variant **ret_dlopen_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) {
#if HAVE_ELFUTILS
_cleanup_close_pair_ int error_pipe[2] = EBADF_PAIR,
return_pipe[2] = EBADF_PAIR,
package_metadata_pipe[2] = EBADF_PAIR,
dlopen_metadata_pipe[2] = EBADF_PAIR;
_cleanup_(sd_json_variant_unrefp) sd_json_variant *package_metadata = NULL, *dlopen_metadata = NULL;
json_pipe[2] = EBADF_PAIR;
_cleanup_(sd_json_variant_unrefp) sd_json_variant *package_metadata = NULL;
_cleanup_free_ char *buf = NULL;
int r;
@ -846,13 +805,7 @@ int parse_elf_object(
}
if (ret_package_metadata) {
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));
r = RET_NERRNO(pipe2(json_pipe, O_CLOEXEC|O_NONBLOCK));
if (r < 0)
return r;
}
@ -865,8 +818,8 @@ int parse_elf_object(
* the file descriptor and writing into these four pipes. */
r = safe_fork_full("(sd-parse-elf)",
NULL,
(int[]){ fd, error_pipe[1], return_pipe[1], package_metadata_pipe[1], dlopen_metadata_pipe[1] },
5,
(int[]){ fd, error_pipe[1], return_pipe[1], json_pipe[1] },
4,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_NEW_USERNS|FORK_WAIT|FORK_REOPEN_LOG,
NULL);
if (r < 0) {
@ -893,13 +846,7 @@ int parse_elf_object(
report_errno_and_exit(error_pipe[1], r);
}
r = parse_elf(
fd,
executable,
root,
ret ? &buf : NULL,
ret_package_metadata ? &package_metadata : NULL,
ret_dlopen_metadata ? &dlopen_metadata : NULL);
r = parse_elf(fd, executable, root, ret ? &buf : NULL, ret_package_metadata ? &package_metadata : NULL);
if (r < 0)
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
* 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)
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");
}
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);
}
error_pipe[1] = safe_close(error_pipe[1]);
return_pipe[1] = safe_close(return_pipe[1]);
package_metadata_pipe[1] = safe_close(package_metadata_pipe[1]);
dlopen_metadata_pipe[1] = safe_close(dlopen_metadata_pipe[1]);
json_pipe[1] = safe_close(json_pipe[1]);
if (ret) {
_cleanup_fclose_ FILE *in = NULL;
@ -982,33 +912,19 @@ int parse_elf_object(
if (ret_package_metadata) {
_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)
return -errno;
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 */
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");
log_warning_errno(r, "Failed to read or parse json metadata, ignoring: %m");
}
if (ret)
*ret = TAKE_PTR(buf);
if (ret_package_metadata)
*ret_package_metadata = TAKE_PTR(package_metadata);
if (ret_dlopen_metadata)
*ret_dlopen_metadata = TAKE_PTR(dlopen_metadata);
return 0;
#else

View File

@ -9,11 +9,4 @@ int dlopen_elf(void);
/* 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.
* 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,
sd_json_variant **ret_dlopen_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);

View File

@ -21,20 +21,20 @@
#include "process-util.h"
#include "string-util.h"
#include "tests.h"
#include "tmpfile-util.h"
#include "uid-range.h"
#include "user-util.h"
#include "virt.h"
TEST(namespace_cleanup_tmpdir) {
{
_cleanup_(namespace_cleanup_tmpdirp) char *dir = NULL;
ASSERT_NOT_NULL(dir = strdup(RUN_SYSTEMD_EMPTY));
_cleanup_(namespace_cleanup_tmpdirp) char *dir;
assert_se(dir = strdup(RUN_SYSTEMD_EMPTY));
}
{
_cleanup_(namespace_cleanup_tmpdirp) char *dir = NULL;
ASSERT_OK(mkdtemp_malloc("/tmp/systemd-test-namespace.XXXXXX", &dir));
_cleanup_(namespace_cleanup_tmpdirp) char *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;
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_OK_ERRNO(stat(b, &y));
assert_se(stat(a, &x) >= 0);
assert_se(stat(b, &y) >= 0);
ASSERT_TRUE(S_ISDIR(x.st_mode));
ASSERT_TRUE(S_ISDIR(y.st_mode));
assert_se(S_ISDIR(x.st_mode));
assert_se(S_ISDIR(y.st_mode));
if (!streq(a, RUN_SYSTEMD_EMPTY)) {
ASSERT_TRUE(startswith(a, A));
ASSERT_EQ((x.st_mode & 01777), 0700U);
ASSERT_NOT_NULL(c = strjoina(a, "/tmp"));
ASSERT_OK_ERRNO(stat(c, &x));
ASSERT_TRUE(S_ISDIR(x.st_mode));
ASSERT_TRUE(FLAGS_SET(x.st_mode, 01777));
ASSERT_OK_ERRNO(rmdir(c));
ASSERT_OK_ERRNO(rmdir(a));
assert_se(startswith(a, A));
assert_se((x.st_mode & 01777) == 0700);
c = strjoina(a, "/tmp");
assert_se(stat(c, &x) >= 0);
assert_se(S_ISDIR(x.st_mode));
assert_se(FLAGS_SET(x.st_mode, 01777));
assert_se(rmdir(c) >= 0);
assert_se(rmdir(a) >= 0);
}
if (!streq(b, RUN_SYSTEMD_EMPTY)) {
ASSERT_TRUE(startswith(b, B));
ASSERT_EQ((y.st_mode & 01777), 0700U);
ASSERT_NOT_NULL(d = strjoina(b, "/tmp"));
ASSERT_OK_ERRNO(stat(d, &y));
ASSERT_TRUE(S_ISDIR(y.st_mode));
ASSERT_TRUE(FLAGS_SET(y.st_mode, 01777));
ASSERT_OK_ERRNO(rmdir(d));
ASSERT_OK_ERRNO(rmdir(b));
assert_se(startswith(b, B));
assert_se((y.st_mode & 01777) == 0700);
d = strjoina(b, "/tmp");
assert_se(stat(d, &y) >= 0);
assert_se(S_ISDIR(y.st_mode));
assert_se(FLAGS_SET(y.st_mode, 01777));
assert_se(rmdir(d) >= 0);
assert_se(rmdir(b) >= 0);
}
}
@ -78,15 +78,18 @@ TEST(tmpdir) {
_cleanup_free_ char *x = NULL, *y = NULL, *z = NULL, *zz = NULL;
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-"));
ASSERT_NOT_NULL(y = strjoin("/var/tmp/systemd-private-", SD_ID128_TO_STRING(bid), "-abcd.service-"));
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_se(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-"));
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-"));
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_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);
}
@ -103,54 +106,54 @@ static void test_shareable_ns(unsigned long nsflag) {
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();
ASSERT_OK_ERRNO(pid1);
assert_se(pid1 >= 0);
if (pid1 == 0) {
r = setup_shareable_ns(s, nsflag);
if (!ERRNO_IS_PRIVILEGE(r))
ASSERT_OK(r);
assert_se(r >= 0 || ERRNO_IS_NEG_PRIVILEGE(r));
_exit(r >= 0 ? r : EX_NOPERM);
}
pid2 = fork();
ASSERT_OK_ERRNO(pid2);
assert_se(pid2 >= 0);
if (pid2 == 0) {
r = setup_shareable_ns(s, nsflag);
if (!ERRNO_IS_PRIVILEGE(r))
ASSERT_OK(r);
assert_se(r >= 0 || ERRNO_IS_NEG_PRIVILEGE(r));
_exit(r >= 0 ? r : EX_NOPERM);
}
pid3 = fork();
ASSERT_OK_ERRNO(pid3);
assert_se(pid3 >= 0);
if (pid3 == 0) {
r = setup_shareable_ns(s, nsflag);
if (!ERRNO_IS_PRIVILEGE(r))
ASSERT_OK(r);
assert_se(r >= 0 || ERRNO_IS_NEG_PRIVILEGE(r));
_exit(r >= 0 ? r : EX_NOPERM);
}
ASSERT_OK(wait_for_terminate(pid1, &si));
ASSERT_EQ(si.si_code, CLD_EXITED);
r = wait_for_terminate(pid1, &si);
assert_se(r >= 0);
assert_se(si.si_code == CLD_EXITED);
if (si.si_status == EX_NOPERM)
permission_denied = true;
else
n += si.si_status;
ASSERT_OK(wait_for_terminate(pid2, &si));
ASSERT_EQ(si.si_code, CLD_EXITED);
r = wait_for_terminate(pid2, &si);
assert_se(r >= 0);
assert_se(si.si_code == CLD_EXITED);
if (si.si_status == EX_NOPERM)
permission_denied = true;
else
n += si.si_status;
ASSERT_OK(wait_for_terminate(pid3, &si));
ASSERT_EQ(si.si_code, CLD_EXITED);
r = wait_for_terminate(pid3, &si);
assert_se(r >= 0);
assert_se(si.si_code == CLD_EXITED);
if (si.si_status == EX_NOPERM)
permission_denied = true;
else
@ -161,7 +164,7 @@ static void test_shareable_ns(unsigned long nsflag) {
if (permission_denied)
return (void) log_tests_skipped("insufficient privileges");
ASSERT_EQ(n, 1);
assert_se(n == 1);
}
TEST(netns) {
@ -203,6 +206,7 @@ TEST(protect_kernel_logs) {
.protect_kernel_logs = true,
};
pid_t pid;
int r;
if (geteuid() > 0) {
(void) log_tests_skipped("not root");
@ -216,30 +220,33 @@ TEST(protect_kernel_logs) {
}
pid = fork();
ASSERT_OK_ERRNO(pid);
assert_se(pid >= 0);
if (pid == 0) {
_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_ERROR_ERRNO(open("/dev/kmsg", O_RDONLY | O_CLOEXEC), EACCES);
assert_se(setresuid(UID_NOBODY, UID_NOBODY, UID_NOBODY) >= 0);
assert_se(open("/dev/kmsg", O_RDONLY | O_CLOEXEC) < 0);
assert_se(errno == EACCES);
_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) {
ASSERT_OK(is_idmapping_supported("/run"));
ASSERT_OK(is_idmapping_supported("/var/lib"));
ASSERT_OK(is_idmapping_supported("/var/cache"));
ASSERT_OK(is_idmapping_supported("/var/log"));
ASSERT_OK(is_idmapping_supported("/etc"));
assert_se(is_idmapping_supported("/run") >= 0);
assert_se(is_idmapping_supported("/var/lib") >= 0);
assert_se(is_idmapping_supported("/var/cache") >= 0);
assert_se(is_idmapping_supported("/var/log") >= 0);
assert_se(is_idmapping_supported("/etc") >= 0);
}
TEST(namespace_is_init) {

View File

@ -18,7 +18,7 @@ systemd-analyze time || :
systemd-analyze critical-chain || :
# 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)
# plot
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
if systemd-analyze --version | grep -q -F "+ELFUTILS"; then
systemd-analyze inspect-elf /lib/systemd/systemd
systemd-analyze inspect-elf --json=short /lib/systemd/systemd | grep -q -F '"elfType":"executable"'
# For some unknown reason the .note.dlopen sections are removed when building with sanitizers, so only
# run this test if we're not running under sanitizers.
if [[ ! -v ASAN_OPTIONS ]]; then
shared="$(ldd /lib/systemd/systemd | grep shared | cut -d' ' -f3)"
systemd-analyze dlopen-metadata "$shared"
systemd-analyze dlopen-metadata --json=short "$shared"
fi
fi
systemd-analyze --threshold=90 security systemd-journald.service