Add ExtraFileDescriptor property to StartTransientUnit dbus API

This adds the ExtraFileDescriptor property to StartTransient dbus API
with format "a(hs)" - array of (file descriptor, name) pairs. The FD
will be passed to the unit via sd_notify like Socket and OpenFile.

systemctl show also shows ExtraFileDescriptorName for these transient
units. We only show the name passed to dbus as the FD numbers will
change once passed over the unix socket and are duplicated, so its
confusing to display the numbers.

We do not add this functionality for systemd-run or general systemd
service units as it is not useful for general systemd services.
Arguably, it could be useful for systemd-run in bash scripts but we
prefer to be cautious and not expose the API yet.

Fixes: #34396
This commit is contained in:
Ryan Wilson
2024-10-07 09:01:48 -07:00
parent f88813b71a
commit 3543456f84
11 changed files with 316 additions and 46 deletions
+23 -7
View File
@@ -1282,7 +1282,13 @@ static int exec_parameters_serialize(const ExecParameters *p, const ExecContext
return r;
}
r = serialize_fd_many(f, fds, "exec-parameters-fds", p->fds, p->n_socket_fds + p->n_storage_fds);
if (p->n_extra_fds > 0) {
r = serialize_item_format(f, "exec-parameters-n-extra-fds", "%zu", p->n_extra_fds);
if (r < 0)
return r;
}
r = serialize_fd_many(f, fds, "exec-parameters-fds", p->fds, p->n_socket_fds + p->n_storage_fds + p->n_extra_fds);
if (r < 0)
return r;
}
@@ -1478,27 +1484,37 @@ static int exec_parameters_deserialize(ExecParameters *p, FILE *f, FDSet *fds) {
if (p->n_storage_fds > (size_t) nr_open)
return -EINVAL; /* too many, someone is playing games with us */
} else if ((val = startswith(l, "exec-parameters-n-extra-fds="))) {
if (p->fds)
return -EINVAL; /* Already received */
r = safe_atozu(val, &p->n_extra_fds);
if (r < 0)
return r;
if (p->n_extra_fds > (size_t) nr_open)
return -EINVAL; /* too many, someone is playing games with us */
} else if ((val = startswith(l, "exec-parameters-fds="))) {
if (p->n_socket_fds + p->n_storage_fds == 0)
if (p->n_socket_fds + p->n_storage_fds + p->n_extra_fds == 0)
return log_warning_errno(
SYNTHETIC_ERRNO(EINVAL),
"Got exec-parameters-fds= without "
"prior exec-parameters-n-socket-fds= or exec-parameters-n-storage-fds=");
if (p->n_socket_fds + p->n_storage_fds > (size_t) nr_open)
"prior exec-parameters-n-socket-fds= or exec-parameters-n-storage-fds= or exec-parameters-n-extra-fds=");
if (p->n_socket_fds + p->n_storage_fds + p->n_extra_fds > (size_t) nr_open)
return -EINVAL; /* too many, someone is playing games with us */
if (p->fds)
return -EINVAL; /* duplicated */
p->fds = new(int, p->n_socket_fds + p->n_storage_fds);
p->fds = new(int, p->n_socket_fds + p->n_storage_fds + p->n_extra_fds);
if (!p->fds)
return log_oom_debug();
/* Ensure we don't leave any FD uninitialized on error, it makes the fuzzer sad */
FOREACH_ARRAY(i, p->fds, p->n_socket_fds + p->n_storage_fds)
FOREACH_ARRAY(i, p->fds, p->n_socket_fds + p->n_storage_fds + p->n_extra_fds)
*i = -EBADF;
r = deserialize_fd_many(fds, val, p->n_socket_fds + p->n_storage_fds, p->fds);
r = deserialize_fd_many(fds, val, p->n_socket_fds + p->n_storage_fds + p->n_extra_fds, p->fds);
if (r < 0)
continue;