From 26a9ed955975c8a278d0cfbda410b7cd00b9d4bc Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Thu, 2 Apr 2026 09:01:16 +0200 Subject: [PATCH 1/2] ssh-proxy: fix use-after-free of borrowed varlink reply reference sd_varlink_call_full() returns borrowed references into the varlink connection's receive buffer (v->current). fetch_machine() stored this borrowed reference with _cleanup_(sd_json_variant_unrefp), which would unref it on error paths -- potentially freeing the parent object while the varlink connection still owns it. On success, TAKE_PTR passed the raw borrowed pointer to the caller, but the varlink connection (and its receive buffer) is freed when fetch_machine returns, leaving the caller with a dangling pointer. Fix by removing the cleanup attribute (the reference is borrowed, not owned) and taking a real ref via sd_json_variant_ref() before returning to the caller, so the data survives the varlink connection's cleanup. Signed-off-by: Christian Brauner (Amutable) --- src/ssh-generator/ssh-proxy.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ssh-generator/ssh-proxy.c b/src/ssh-generator/ssh-proxy.c index bfb91b5867..fa42c5bee8 100644 --- a/src/ssh-generator/ssh-proxy.c +++ b/src/ssh-generator/ssh-proxy.c @@ -282,7 +282,7 @@ static int fetch_machine(const char *machine, RuntimeScope scope, sd_json_varian if (r < 0) return log_error_errno(r, "Failed to connect to machined on %s: %m", addr); - _cleanup_(sd_json_variant_unrefp) sd_json_variant *result = NULL; + sd_json_variant *result = NULL; const char *error_id; r = sd_varlink_callbo( vl, @@ -303,7 +303,9 @@ static int fetch_machine(const char *machine, RuntimeScope scope, sd_json_varian return log_error_errno(r, "Failed to issue io.systemd.Machine.List() varlink call: %s", error_id); } - *ret = TAKE_PTR(result); + /* result is a borrowed reference into the varlink connection's receive buffer. Take a real ref so + * that it survives the cleanup of vl below. */ + *ret = sd_json_variant_ref(result); return 0; } From 5b5423efa37d0c865c99ac02a22821f39ffdd2e1 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Wed, 1 Apr 2026 23:23:18 +0200 Subject: [PATCH 2/2] sd-json: fix sd_json_variant_unsigned() dispatching to wrong accessor for references sd_json_variant_unsigned() incorrectly calls sd_json_variant_integer() for reference-type variants instead of recursing to itself. This silently returns 0 for unsigned values in the range INT64_MAX+1 through UINT64_MAX, since sd_json_variant_integer() cannot represent them. The sibling functions sd_json_variant_integer() and sd_json_variant_real() correctly recurse to themselves. Signed-off-by: Christian Brauner (Amutable) --- src/libsystemd/sd-json/sd-json.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsystemd/sd-json/sd-json.c b/src/libsystemd/sd-json/sd-json.c index 03557d3ac6..6245d471b7 100644 --- a/src/libsystemd/sd-json/sd-json.c +++ b/src/libsystemd/sd-json/sd-json.c @@ -1003,7 +1003,7 @@ _public_ uint64_t sd_json_variant_unsigned(sd_json_variant *v) { if (!json_variant_is_regular(v)) goto mismatch; if (v->is_reference) - return sd_json_variant_integer(v->reference); + return sd_json_variant_unsigned(v->reference); switch (v->type) {