From 2108812a76bd078a2bbd7583308ff18bf01f2383 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Tue, 29 Apr 2025 14:47:59 +0200
Subject: [PATCH 1/3] coredump: restore compatibility with older patterns

This was broken in f45b8015513d38ee5f7cc361db9c5b88c9aae704. Unfortunately
the review does not talk about backward compatibility at all. There are
two places where it matters:
- During upgrades, the replacement of kernel.core_pattern is asynchronous.
  For example, during rpm upgrades, it would be updated a post-transaction
  file trigger. In other scenarios, the update might only happen after
  reboot. We have a potentially long window where the old pattern is in
  place. We need to capture coredumps during upgrades too.
- With --backtrace. The interface of --backtrace, in hindsight, is not
  great. But there are users of --backtrace which were written to use
  a specific set of arguments, and we can't just break compatiblity.
  One example is systemd-coredump-python, but there are also reports of
  users using --backtrace to generate coredump logs.

Thus, we require the original set of args, and will use the additional args if
found.

A test is added to verify that --backtrace works with and without the optional
args.

(cherry picked from commit ded0aac389e647d35bce7ec4a48e718d77c0435b)
(cherry picked from commit f9b8b75c11bba9b63096904be98cc529c304eb97)
(cherry picked from commit 385a33b043406ad79a7207f3906c3b15192a3333)
(cherry picked from commit c6f79626b6d175c6a5b62b8c5d957a83eb882301)
(cherry picked from commit 9f02346d50e33c24acf879ce4dd5937d56473325)
(cherry picked from commit ac0aa5d1fdc21db1ef035fce562cb6fc8602b544)

Upstream-Status: Backport [https://github.com/systemd/systemd-stable/commit/cadd1b1a1f39fd13b1115a10f563017201d7b56a]

Signed-off-by: Chen Qi <Qi.Chen@windriver.com>
---
 src/coredump/coredump.c | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index 79280ab986..d598f6f59a 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -84,8 +84,12 @@ enum {
         META_ARGV_SIGNAL,       /* %s: number of signal causing dump */
         META_ARGV_TIMESTAMP,    /* %t: time of dump, expressed as seconds since the Epoch (we expand this to µs granularity) */
         META_ARGV_RLIMIT,       /* %c: core file size soft resource limit */
-        META_ARGV_HOSTNAME,     /* %h: hostname */
+        _META_ARGV_REQUIRED,
+        /* The fields below were added to kernel/core_pattern at later points, so they might be missing. */
+        META_ARGV_HOSTNAME = _META_ARGV_REQUIRED,  /* %h: hostname */
         _META_ARGV_MAX,
+        /* If new fields are added, they should be added here, to maintain compatibility
+         * with callers which don't know about the new fields. */
 
         /* The following indexes are cached for a couple of special fields we use (and
          * thereby need to be retrieved quickly) for naming coredump files, and attaching
@@ -96,7 +100,7 @@ enum {
         _META_MANDATORY_MAX,
 
         /* The rest are similar to the previous ones except that we won't fail if one of
-         * them is missing. */
+         * them is missing in a message sent over the socket. */
 
         META_EXE = _META_MANDATORY_MAX,
         META_UNIT,
@@ -1278,14 +1282,17 @@ static int gather_pid_metadata_from_argv(
         char *t;
 
         /* We gather all metadata that were passed via argv[] into an array of iovecs that
-         * we'll forward to the socket unit */
+         * we'll forward to the socket unit.
+         *
+         * We require at least _META_ARGV_REQUIRED args, but will accept more.
+         * We know how to parse _META_ARGV_MAX args. The rest will be ignored. */
 
-        if (argc < _META_ARGV_MAX)
+        if (argc < _META_ARGV_REQUIRED)
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                       "Not enough arguments passed by the kernel (%i, expected %i).",
-                                       argc, _META_ARGV_MAX);
+                                       "Not enough arguments passed by the kernel (%i, expected between %i and %i).",
+                                       argc, _META_ARGV_REQUIRED, _META_ARGV_MAX);
 
-        for (int i = 0; i < _META_ARGV_MAX; i++) {
+        for (int i = 0; i < MIN(argc, _META_ARGV_MAX); i++) {
 
                 t = argv[i];
 
-- 
2.34.1

