From efafddcfbc76b38bb494053ae798d6cea6508b60 Mon Sep 17 00:00:00 2001 From: Martin Pitt Date: Fri, 23 Oct 2026 04:22:57 +0000 Subject: [PATCH] imdsd: report running out of retries as Timeout When connection errors or token refreshes used up the retries, the request previously failed with the generic `io.systemd.System` error. In indirect mode the parent forwards only the error name, so clients saw no reason at all. Running out of retries means that IMDS did not answer in time, which the overall timeout already reports as `io.systemd.InstanceMetadata.Timeout`. Use that for exhausted retries as well. Signed-off-by: Martin Pitt (cherry picked from commit 84c768e83b493daa3a04033e48ffcee6668e4f34) --- src/imds/imdsd.c | 4 ++++ .../TEST-74-AUX-UTILS.units/fake-imds.py | 2 ++ test/units/TEST-74-AUX-UTILS.imds.sh | 12 ++++++++++++ 3 files changed, 18 insertions(+) diff --git a/src/imds/imdsd.c b/src/imds/imdsd.c index 12a88dfe230..14aba1c5e45 100644 --- a/src/imds/imdsd.c +++ b/src/imds/imdsd.c @@ -923,6 +923,8 @@ static int curl_on_finished(CurlSlot *slot, CURL *curl, CURLcode result, void *u /* Automatically retry on some transient errors from curl itself */ r = context_schedule_retry(c); + if (r == -EUCLEAN) + return context_fail_full(c, r, "io.systemd.InstanceMetadata.Timeout"); if (r < 0) return context_fail(c, r); @@ -975,6 +977,8 @@ static int curl_on_finished(CurlSlot *slot, CURL *curl, CURLcode result, void *u r = context_validate_data_http_status(c, status); if (r == -ENOENT) return context_fail_full(c, r, "io.systemd.InstanceMetadata.KeyNotFound"); + if (r == -EUCLEAN) + return context_fail_full(c, r, "io.systemd.InstanceMetadata.Timeout"); if (r < 0) return context_fail(c, r); if (r == 0) /* Immediately restarted */ diff --git a/test/integration-tests/TEST-74-AUX-UTILS/TEST-74-AUX-UTILS.units/fake-imds.py b/test/integration-tests/TEST-74-AUX-UTILS/TEST-74-AUX-UTILS.units/fake-imds.py index d3c41d174aa..af66ee307ac 100755 --- a/test/integration-tests/TEST-74-AUX-UTILS/TEST-74-AUX-UTILS.units/fake-imds.py +++ b/test/integration-tests/TEST-74-AUX-UTILS/TEST-74-AUX-UTILS.units/fake-imds.py @@ -49,6 +49,8 @@ class Handler(BaseHTTPRequestHandler): self.send_error(401) else: self.send_text(b'fresh') + elif self.path == '/unauthorized': + self.send_error(401) elif self.path == '/userdata': body = b'{"systemd.credentials":[{"name":"acredtest","text":"avalue"}]}' self.send_response(200) diff --git a/test/units/TEST-74-AUX-UTILS.imds.sh b/test/units/TEST-74-AUX-UTILS.imds.sh index 156f155484f..a0fed3fbfab 100755 --- a/test/units/TEST-74-AUX-UTILS.imds.sh +++ b/test/units/TEST-74-AUX-UTILS.imds.sh @@ -48,6 +48,12 @@ IMDSD_TOKEN=("${IMDSD[@]}" --interface=dummy0 --token-url=http://192.168.47.11:8 assert_eq "$(RUNTIME_DIRECTORY="$WORK_DIR/runtime" "${IMDSD_TOKEN[@]}" /expiring)" "fresh" assert_eq "$(RUNTIME_DIRECTORY="$WORK_DIR/runtime" "${IMDSD_TOKEN[@]}" --data-url=http://192.168.47.11:1 /expiring)" "fresh" +# Running out of token refreshes is reported as timeout +(! "${IMDSD_TOKEN[@]}" /unauthorized 2>"$WORK_DIR/unauthorized.err") +cat "$WORK_DIR/unauthorized.err" +grep -F "io.systemd.InstanceMetadata.Timeout" "$WORK_DIR/unauthorized.err" >/dev/null +(! grep -F "Overall timeout reached" "$WORK_DIR/unauthorized.err" >/dev/null) + # Missing keys: both real and fake IMDS answer 404 with a non-empty body (! "${IMDSD[@]}" /nonexistent 2>"$WORK_DIR/imdsd.err") cat "$WORK_DIR/imdsd.err" @@ -55,6 +61,12 @@ cat "$WORK_DIR/imdsd.err" grep -F "io.systemd.InstanceMetadata.KeyNotFound" "$WORK_DIR/imdsd.err" >/dev/null (! grep -F "io.systemd.System" "$WORK_DIR/imdsd.err" >/dev/null) +# Running out of retries for connection errors is reported as timeout. Slow, as this waits for all retries. +(! "${IMDSD[@]}" --interface=dummy0 --data-url=http://192.168.47.11:1 /hostname 2>"$WORK_DIR/refused.err") +cat "$WORK_DIR/refused.err" +(! grep -F "Overall timeout reached" "$WORK_DIR/refused.err" >/dev/null) +grep -F "io.systemd.InstanceMetadata.Timeout" "$WORK_DIR/refused.err" >/dev/null + # Then, try it as Varlink service mkdir -p /run/systemd/system/systemd-imdsd@.service.d/ cat >/run/systemd/system/systemd-imdsd@.service.d/50-env.conf <