]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-varlink: decrement connection counters on failure
authorShiroKSH <kushidashiro@gmail.com>
Wed, 12 Aug 2026 19:10:33 +0000 (19:10 +0000)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 14 Aug 2026 14:56:19 +0000 (23:56 +0900)
Previously, sd_varlink_server_add_connection_pair() did not decrement
the connection counters when json_stream_attach_fds() failed.

Set the ucred before calling json_stream_attach_fds() so that
sd_varlink_close() also decrements the counters when it fails.

src/libsystemd/sd-varlink/sd-varlink.c
src/libsystemd/sd-varlink/test-varlink.c

index cb8864635eabed7d8061c12d5a82cab80e9da280..f7de8b8f436e87a067caf205472aa2450a667950 100644 (file)
@@ -3438,9 +3438,14 @@ _public_ int sd_varlink_server_add_connection_pair(
         v->server = sd_varlink_server_ref(server);
         sd_varlink_ref(v);
 
+        if (ucred_acquired)
+                json_stream_set_peer_ucred(&v->stream, &ucred);
+
         r = json_stream_attach_fds(&v->stream, input_fd, output_fd);
-        if (r < 0)
+        if (r < 0) {
+                sd_varlink_close(v);
                 return r;
+        }
 
         if (server->flags & SD_VARLINK_SERVER_INHERIT_USERDATA)
                 v->userdata = server->userdata;
@@ -3450,9 +3455,6 @@ _public_ int sd_varlink_server_add_connection_pair(
         if (FLAGS_SET(server->flags, SD_VARLINK_SERVER_UPGRADABLE))
                 json_stream_set_flags(&v->stream, JSON_STREAM_BOUNDED_READS, true);
 
-        if (ucred_acquired)
-                json_stream_set_peer_ucred(&v->stream, &ucred);
-
         _cleanup_free_ char *desc = NULL;
         if (asprintf(&desc, "%s-%i-%i", varlink_server_description(server), input_fd, output_fd) >= 0)
                 json_stream_set_description(&v->stream, desc);
index 73b63c45d7217e5922c0ea265a7bb32e7fbe9a39..41d5f53deb2d01ba4e38ccbec899ceceeac5c1bc 100644 (file)
@@ -1504,4 +1504,33 @@ TEST(ctrunc) {
         ASSERT_OK(r);
 }
 
+TEST(add_connection_failure_cleanup) {
+        _cleanup_(sd_varlink_server_unrefp) sd_varlink_server *s = NULL;
+        _cleanup_close_pair_ int fds[2] = EBADF_PAIR;
+        const struct ucred ucred = {
+                .pid = getpid(),
+                .uid = getuid(),
+                .gid = getgid(),
+        };
+
+        ASSERT_OK(sd_varlink_server_new(&s, SD_VARLINK_SERVER_ACCOUNT_UID));
+        ASSERT_OK(sd_varlink_server_set_connections_per_uid_max(s, 1));
+        ASSERT_OK_ERRNO(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds));
+
+        int bad_fd = ASSERT_OK(memfd_new("closed-fd"));
+        ASSERT_OK_ERRNO(close(bad_fd));
+
+        ASSERT_ERROR(sd_varlink_server_add_connection_pair(s, fds[0], bad_fd, &ucred, /* ret= */ NULL), EBADF);
+        ASSERT_EQ(sd_varlink_server_current_connections(s), 0U);
+
+        sd_varlink *v = NULL;
+        ASSERT_OK(sd_varlink_server_add_connection(s, fds[0], &v));
+        TAKE_FD(fds[0]);
+        ASSERT_NOT_NULL(v);
+        ASSERT_EQ(sd_varlink_server_current_connections(s), 1U);
+
+        ASSERT_OK_POSITIVE(sd_varlink_close(v));
+        ASSERT_EQ(sd_varlink_server_current_connections(s), 0U);
+}
+
 DEFINE_TEST_MAIN(LOG_DEBUG);