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) <brauner@kernel.org>
This commit is contained in:
Christian Brauner
2026-04-06 22:02:51 +02:00
parent 454d9c1be1
commit 26a9ed9559
+4 -2
View File
@@ -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;
}