varlink: add helper that adds a connection via stdio to a varlink server

This adds varlink_server_add_connection_stdio() as wrapper around
varlink_server_add_connection_pair(), that steals stdin/stdout fds and
turns them into a varlink connection. To be safe it replaces
stdin/stdout with /dev/null fds.
This commit is contained in:
Lennart Poettering 2024-04-25 10:56:00 +02:00
parent e73ae07b52
commit 4120151f7b
2 changed files with 61 additions and 0 deletions

View file

@ -3703,6 +3703,66 @@ int varlink_server_listen_address(VarlinkServer *s, const char *address, mode_t
return 0;
}
int varlink_server_add_connection_stdio(VarlinkServer *s, Varlink **ret) {
_cleanup_close_ int input_fd = -EBADF, output_fd = -EBADF;
int r;
assert_return(s, -EINVAL);
input_fd = fcntl(STDIN_FILENO, F_DUPFD_CLOEXEC, 3);
if (input_fd < 0)
return -errno;
output_fd = fcntl(STDOUT_FILENO, F_DUPFD_CLOEXEC, 3);
if (output_fd < 0)
return -errno;
r = rearrange_stdio(-EBADF, -EBADF, STDERR_FILENO);
if (r < 0)
return r;
r = fd_nonblock(input_fd, true);
if (r < 0)
return r;
r = fd_nonblock(output_fd, true);
if (r < 0)
return r;
struct stat input_st;
if (fstat(input_fd, &input_st) < 0)
return -errno;
struct stat output_st;
if (fstat(output_fd, &output_st) < 0)
return -errno;
/* If stdin/stdout are both pipes and have the same owning uid/gid then let's synthesize a "struct
* ucred" from the owning UID/GID, since we got them passed in with such ownership. We'll not fill in
* the PID however, since there's no way to know which process created a pipe. */
struct ucred ucred, *pucred;
if (S_ISFIFO(input_st.st_mode) &&
S_ISFIFO(output_st.st_mode) &&
input_st.st_uid == output_st.st_uid &&
input_st.st_gid == output_st.st_gid) {
ucred = (struct ucred) {
.uid = input_st.st_uid,
.gid = input_st.st_gid,
};
pucred = &ucred;
} else
pucred = NULL;
r = varlink_server_add_connection_pair(s, input_fd, output_fd, pucred, ret);
if (r < 0)
return r;
TAKE_FD(input_fd);
TAKE_FD(output_fd);
return 0;
}
int varlink_server_listen_auto(VarlinkServer *s) {
_cleanup_strv_free_ char **names = NULL;
int r, n = 0;

View file

@ -222,6 +222,7 @@ 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);
int varlink_server_add_connection_stdio(VarlinkServer *s, Varlink **ret);
/* Bind callbacks */
int varlink_server_bind_method(VarlinkServer *s, const char *method, VarlinkMethod callback);