]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
varlink: add new call varlink_server_add_connection_pair() for two-fd servers
authorLennart Poettering <lennart@poettering.net>
Thu, 25 Apr 2024 08:55:23 +0000 (10:55 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 27 Jun 2024 07:41:54 +0000 (09:41 +0200)
This adds the server-side for varlink connections over two distinct fds.

src/shared/varlink.c
src/shared/varlink.h

index fea330b86de53e72e56c4ded11354ba16c10a97e..563e81472a499e3821ca8a5ee51efeb03e7a5a72 100644 (file)
@@ -3464,19 +3464,34 @@ static int count_connection(VarlinkServer *server, const struct ucred *ucred) {
         return 0;
 }
 
-int varlink_server_add_connection(VarlinkServer *server, int fd, Varlink **ret) {
+int varlink_server_add_connection_pair(
+                VarlinkServer *server,
+                int input_fd,
+                int output_fd,
+                const struct ucred *override_ucred,
+                Varlink **ret) {
+
         _cleanup_(varlink_unrefp) Varlink *v = NULL;
         struct ucred ucred = UCRED_INVALID;
         bool ucred_acquired;
         int r;
 
         assert_return(server, -EINVAL);
-        assert_return(fd >= 0, -EBADF);
+        assert_return(input_fd >= 0, -EBADF);
+        assert_return(output_fd >= 0, -EBADF);
 
         if ((server->flags & (VARLINK_SERVER_ROOT_ONLY|VARLINK_SERVER_ACCOUNT_UID)) != 0) {
-                r = getpeercred(fd, &ucred);
-                if (r < 0)
-                        return varlink_server_log_errno(server, r, "Failed to acquire peer credentials of incoming socket, refusing: %m");
+
+                if (override_ucred)
+                        ucred = *override_ucred;
+                else {
+                        if (input_fd != output_fd)
+                                return varlink_server_log_errno(server, SYNTHETIC_ERRNO(EOPNOTSUPP), "Cannot determine peer identity of connection with separate input/output, refusing: %m");
+
+                        r = getpeercred(input_fd, &ucred);
+                        if (r < 0)
+                                return varlink_server_log_errno(server, r, "Failed to acquire peer credentials of incoming socket, refusing: %m");
+                }
 
                 ucred_acquired = true;
 
@@ -3496,7 +3511,8 @@ int varlink_server_add_connection(VarlinkServer *server, int fd, Varlink **ret)
         if (r < 0)
                 return r;
 
-        v->input_fd = v->output_fd = fd;
+        v->input_fd = input_fd;
+        v->output_fd = output_fd;
         if (server->flags & VARLINK_SERVER_INHERIT_USERDATA)
                 v->userdata = server->userdata;
 
@@ -3506,7 +3522,7 @@ int varlink_server_add_connection(VarlinkServer *server, int fd, Varlink **ret)
         }
 
         _cleanup_free_ char *desc = NULL;
-        if (asprintf(&desc, "%s-%i", varlink_server_description(server), fd) >= 0)
+        if (asprintf(&desc, "%s-%i-%i", varlink_server_description(server), input_fd, output_fd) >= 0)
                 v->description = TAKE_PTR(desc);
 
         /* Link up the server and the connection, and take reference in both directions. Note that the
@@ -3534,6 +3550,10 @@ int varlink_server_add_connection(VarlinkServer *server, int fd, Varlink **ret)
         return 0;
 }
 
+int varlink_server_add_connection(VarlinkServer *server, int fd, Varlink **ret) {
+        return varlink_server_add_connection_pair(server, fd, fd, /* override_ucred= */ NULL, ret);
+}
+
 static VarlinkServerSocket *varlink_server_socket_free(VarlinkServerSocket *ss) {
         if (!ss)
                 return NULL;
index 1ae65424b1e6811b8d4c74ef91bdbe6dc87ec364..2585c45efd6b05de96b296bd0d7494a9372baac7 100644 (file)
@@ -221,6 +221,7 @@ int varlink_server_listen_address(VarlinkServer *s, const char *address, mode_t
 int varlink_server_listen_fd(VarlinkServer *s, int fd);
 int varlink_server_listen_auto(VarlinkServer *s);
 int varlink_server_add_connection(VarlinkServer *s, int fd, Varlink **ret);
+int varlink_server_add_connection_pair(VarlinkServer *s, int input_fd, int output_fd, const struct ucred *ucred_override, Varlink **ret);
 
 /* Bind callbacks */
 int varlink_server_bind_method(VarlinkServer *s, const char *method, VarlinkMethod callback);