summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2022-01-03 09:24:03 +0100
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2022-01-04 16:27:51 +0100
commite4d4c5f9eecb9600d60e08c5093765996acff4a5 (patch)
treec2a70818fa6376860f637f95e3dd18e7c32e80fb
parentbdcc3b0713f4c50d09857083c4ae27e8fb3acaad (diff)
downloadsystemd-e4d4c5f9eecb9600d60e08c5093765996acff4a5.tar.gz
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. (cherry picked from commit c790632cabf5691b0910fc6b7a5c6af31a7786aa)
-rw-r--r--src/coredump/coredump.c39
1 files changed, 22 insertions, 17 deletions
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index 9e0dafb1ce..6a6e9765d4 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -813,16 +813,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],
@@ -857,21 +860,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) {
@@ -1181,7 +1187,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);
@@ -1191,7 +1197,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);