1
0
mirror of https://github.com/systemd/systemd synced 2025-10-06 00:13:24 +02:00

varlinkctl: optionally push fds to server

This commit is contained in:
Lennart Poettering
2025-05-26 13:19:14 +02:00
parent 0261fe571b
commit b4c2e2b970
2 changed files with 76 additions and 0 deletions

View File

@@ -338,6 +338,22 @@
</listitem>
</varlistentry>
<varlistentry>
<term><option>--push-fd=</option></term>
<listitem>
<para>Takes a numeric file descriptor number as parameter. May be used to pass a file
descriptor along with the method call, if the underlying transport supports this. May be used
multiple times to pass multiple file descriptors, retaining the order in which they are
specified. The specified file descriptors must be passed to the <command>varlinkctl</command>
invocation. Optionally, in place of a numeric file descriptor number an absolute or relative file
system path (the latter must be prefixed with <literal>./</literal>) may be specified, which is
opened in read-only mode.</para>
<xi:include href="version-info.xml" xpointer="v258"/>
</listitem>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="no-pager" />
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />

View File

@@ -18,6 +18,7 @@
#include "memfd-util.h"
#include "pager.h"
#include "parse-argument.h"
#include "parse-util.h"
#include "pretty-print.h"
#include "process-util.h"
#include "string-util.h"
@@ -29,6 +30,11 @@
#include "verbs.h"
#include "version.h"
typedef struct PushFds {
int *fds;
size_t n_fds;
} PushFds;
static sd_json_format_flags_t arg_json_format_flags = SD_JSON_FORMAT_OFF;
static PagerFlags arg_pager_flags = 0;
static sd_varlink_method_flags_t arg_method_flags = 0;
@@ -37,8 +43,17 @@ static bool arg_quiet = false;
static char **arg_graceful = NULL;
static usec_t arg_timeout = 0;
static bool arg_exec = false;
static PushFds arg_push_fds = {};
static void push_fds_done(PushFds *p) {
assert(p);
close_many_and_free(p->fds, p->n_fds);
*p = (PushFds) {};
}
STATIC_DESTRUCTOR_REGISTER(arg_graceful, strv_freep);
STATIC_DESTRUCTOR_REGISTER(arg_push_fds, push_fds_done);
static int help(void) {
_cleanup_free_ char *link = NULL;
@@ -80,6 +95,7 @@ static int help(void) {
" --graceful=ERROR Treat specified Varlink error as success\n"
" --timeout=SECS Maximum time to wait for method call completion\n"
" -E Short for --more --timeout=infinity\n"
" --push-fd=FD Pass the specified fd along with method call\n"
"\nSee the %2$s for details.\n",
program_invocation_short_name,
link,
@@ -107,6 +123,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_GRACEFUL,
ARG_TIMEOUT,
ARG_EXEC,
ARG_PUSH_FD,
};
static const struct option options[] = {
@@ -121,6 +138,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "graceful", required_argument, NULL, ARG_GRACEFUL },
{ "timeout", required_argument, NULL, ARG_TIMEOUT },
{ "exec", no_argument, NULL, ARG_EXEC },
{ "push-fd", required_argument, NULL, ARG_PUSH_FD },
{},
};
@@ -205,6 +223,34 @@ static int parse_argv(int argc, char *argv[]) {
arg_exec = true;
break;
case ARG_PUSH_FD: {
if (!GREEDY_REALLOC(arg_push_fds.fds, arg_push_fds.n_fds + 1))
return log_oom();
_cleanup_close_ int add_fd = -EBADF;
if (STARTSWITH_SET(optarg, "/", "./")) {
/* We usually expect a numeric fd spec, but as an extension let's treat this
* as a path to open in read-only mode in case this is clearly an absolute or
* relative path */
add_fd = open(optarg, O_CLOEXEC|O_RDONLY|O_NOCTTY);
if (add_fd < 0)
return log_error_errno(errno, "Failed to open '%s': %m", optarg);
} else {
int parsed_fd = parse_fd(optarg);
if (parsed_fd < 0)
return log_error_errno(parsed_fd, "Failed to parse --push-fd= parameter: %s", optarg);
/* Make a copy, so that the same fd could be used multiple times in a reasonable
* way. This also validates the fd early */
add_fd = fcntl(parsed_fd, F_DUPFD_CLOEXEC, 3);
if (add_fd < 0)
return log_error_errno(errno, "Failed to duplicate file descriptor %i: %m", parsed_fd);
}
arg_push_fds.fds[arg_push_fds.n_fds++] = TAKE_FD(add_fd);
break;
}
case '?':
return -EINVAL;
@@ -616,6 +662,20 @@ static int verb_call(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
if (arg_push_fds.n_fds > 0) {
r = sd_varlink_set_allow_fd_passing_output(vl, true);
if (r < 0)
return log_error_errno(r, "Failed to enable fd passing: %m");
FOREACH_ARRAY(f, arg_push_fds.fds, arg_push_fds.n_fds) {
r = sd_varlink_push_fd(vl, *f);
if (r < 0)
return log_error_errno(r, "Failed to push file descriptor: %m");
TAKE_FD(*f); /* we passed ownership away */
}
}
if (arg_collect) {
sd_json_variant *reply = NULL;
const char *error = NULL;