diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2022-01-03 09:24:03 +0100 |
---|---|---|
committer | Luca Boccassi <luca.boccassi@gmail.com> | 2022-01-03 23:44:44 +0100 |
commit | c790632cabf5691b0910fc6b7a5c6af31a7786aa (patch) | |
tree | fc09f8c4f5e67d071d18a006f7a8b0059c1d6ec1 /src/coredump | |
parent | Merge pull request #21985 from yuwata/elf-util-cleanups (diff) | |
download | systemd-c790632cabf5691b0910fc6b7a5c6af31a7786aa.tar.xz systemd-c790632cabf5691b0910fc6b7a5c6af31a7786aa.zip |
coredump: do not crash if we failed to acquire exe path
The COREDUMP_EXE attribute is "optional", i.e. we continue to process the
crash even if we didn't acquire it. The coredump generation code assumed
that it is always available:
#5 endswith at ../src/fundamental/string-util-fundamental.c:41
[ endswith() is called with NULL here, and an assertion fails. ]
#6 submit_coredump at ../src/coredump/coredump.c:823
#7 process_socket at ../src/coredump/coredump.c:1038
#8 run at ../src/coredump/coredump.c:1413
We use the exe path for loop detection, and also (ultimately) pass it to
dwfl_core_file_report(). The latter seems to be fine will NULL, so let's just
change our code to look at COMM, which should be more reliable anyway.
Fixes https://bugzilla.redhat.com/show_bug.cgi?id=2036517.
Diffstat (limited to 'src/coredump')
-rw-r--r-- | src/coredump/coredump.c | 39 |
1 files changed, 22 insertions, 17 deletions
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index f7f2f194b4..3e38efe552 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -812,16 +812,19 @@ static int submit_coredump( return log_error_errno(r, "Failed to drop privileges: %m"); /* Try to get a stack trace if we can */ - if (coredump_size > arg_process_size_max) { + if (coredump_size > arg_process_size_max) log_debug("Not generating stack trace: core size %"PRIu64" is greater " "than %"PRIu64" (the configured maximum)", coredump_size, arg_process_size_max); - } else if (coredump_fd >= 0) + else if (coredump_fd >= 0) { + bool skip = startswith(context->meta[META_COMM], "systemd-coredum"); /* COMM is 16 bytes usually */ + (void) parse_elf_object(coredump_fd, context->meta[META_EXE], - /* fork_disable_dump= */endswith(context->meta[META_EXE], "systemd-coredump"), /* avoid loops */ + /* fork_disable_dump= */ skip, /* avoid loops */ &stacktrace, &json_metadata); + } log: core_message = strjoina("Process ", context->meta[META_ARGV_PID], @@ -856,21 +859,24 @@ log: (void) iovw_put_string_field(iovw, "COREDUMP_PACKAGE_JSON=", formatted_json); } - JSON_VARIANT_OBJECT_FOREACH(module_name, module_json, json_metadata) { - JsonVariant *package_name, *package_version; + /* In the unlikely scenario that context->meta[META_EXE] is not available, + * let's avoid guessing the module name and skip the loop. */ + if (context->meta[META_EXE]) + JSON_VARIANT_OBJECT_FOREACH(module_name, module_json, json_metadata) { + JsonVariant *t; - /* We only add structured fields for the 'main' ELF module */ - if (!path_equal_filename(module_name, context->meta[META_EXE])) - continue; + /* We only add structured fields for the 'main' ELF module, and only if we can identify it. */ + if (!path_equal_filename(module_name, context->meta[META_EXE])) + continue; - package_name = json_variant_by_key(module_json, "name"); - if (package_name) - (void) iovw_put_string_field(iovw, "COREDUMP_PACKAGE_NAME=", json_variant_string(package_name)); + t = json_variant_by_key(module_json, "name"); + if (t) + (void) iovw_put_string_field(iovw, "COREDUMP_PACKAGE_NAME=", json_variant_string(t)); - package_version = json_variant_by_key(module_json, "version"); - if (package_version) - (void) iovw_put_string_field(iovw, "COREDUMP_PACKAGE_VERSION=", json_variant_string(package_version)); - } + t = json_variant_by_key(module_json, "version"); + if (t) + (void) iovw_put_string_field(iovw, "COREDUMP_PACKAGE_VERSION=", json_variant_string(t)); + } /* Optionally store the entire coredump in the journal */ if (arg_storage == COREDUMP_STORAGE_JOURNAL && coredump_fd >= 0) { @@ -1180,7 +1186,7 @@ static int gather_pid_metadata(struct iovec_wrapper *iovw, Context *context) { if (r < 0) return r; - /* The following are optional but we used them if present */ + /* The following are optional, but we use them if present. */ r = get_process_exe(pid, &t); if (r >= 0) r = iovw_put_string_field_free(iovw, "COREDUMP_EXE=", t); @@ -1190,7 +1196,6 @@ static int gather_pid_metadata(struct iovec_wrapper *iovw, Context *context) { if (cg_pid_get_unit(pid, &t) >= 0) (void) iovw_put_string_field_free(iovw, "COREDUMP_UNIT=", t); - /* The next are optional */ if (cg_pid_get_user_unit(pid, &t) >= 0) (void) iovw_put_string_field_free(iovw, "COREDUMP_USER_UNIT=", t); |