The varlinkctl utility in systemd supports fork+execve'ing a process rather than utilizing the traditional method of connecting to an existing UNIX socket.
When invoking an executable in this manner, it creates a connected UNIX socket via socketpair and passes one end to the executable as file descriptor 3.
varlinkctl call ./a.out com.example.Method '{}'
Passing this file descriptor as listen_fd to varlink_service_new fails as the library attempts to call accept4 on the connected socket.
It would be great if varlink_service_new detects whether listen_fd is a connected UNIX socket, rather than a listening socket, and assumes it's an already accepted connection.
Systemd's Varlink services do roughly this to tell if the file descriptor is a listening socket passed by the service's corresponding .socket unit, or is directly invoked via varlinkctl:
int b;
socklen_t l = sizeof(b);
if (getsockopt(listen_fd, SOL_SOCKET, SO_ACCEPTCONN, &b, &l) < 0) {
// TODO: errno
}
if (b) {
// This is a listening socket
} else {
// This is a connected socket
}
The
varlinkctl
utility in systemd supports fork+execve'ing a process rather than utilizing the traditional method of connecting to an existing UNIX socket.When invoking an executable in this manner, it creates a connected UNIX socket via
socketpair
and passes one end to the executable as file descriptor 3.Passing this file descriptor as
listen_fd
tovarlink_service_new
fails as the library attempts to callaccept4
on the connected socket.It would be great if
varlink_service_new
detects whetherlisten_fd
is a connected UNIX socket, rather than a listening socket, and assumes it's an already accepted connection.Systemd's Varlink services do roughly this to tell if the file descriptor is a listening socket passed by the service's corresponding
.socket
unit, or is directly invoked viavarlinkctl
: