]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
ssh-proxy: fix use-after-free of borrowed varlink reply reference
authorChristian Brauner <brauner@kernel.org>
Thu, 2 Apr 2026 07:01:16 +0000 (09:01 +0200)
committerChristian Brauner <brauner@kernel.org>
Mon, 6 Apr 2026 20:02:51 +0000 (22:02 +0200)
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>
src/ssh-generator/ssh-proxy.c

index bfb91b5867c4eca23b1c3a58fcb45ca8bbc4b784..fa42c5bee8021c58c34d2f2bd94fb6775aa70810 100644 (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;
 }