#include "terminal-util.h"
#include "tmpfile-util.h"
#include "umask-util.h"
-#include "unit.h"
+#include "unit-serialize.h"
#include "user-util.h"
#include "utmp-wtmp.h"
return std_input;
}
-static int fixup_output(ExecOutput std_output, int socket_fd) {
+static int fixup_output(ExecOutput output, int socket_fd) {
- if (std_output == EXEC_OUTPUT_SOCKET && socket_fd < 0)
+ if (output == EXEC_OUTPUT_SOCKET && socket_fd < 0)
return EXEC_OUTPUT_INHERIT;
- return std_output;
+ return output;
}
static int setup_input(
o == EXEC_OUTPUT_INHERIT &&
i == EXEC_INPUT_NULL &&
!is_terminal_input(context->std_input) &&
- getppid () != 1)
+ getppid() != 1)
return fileno;
/* Duplicate from stdout if possible */
case EXEC_OUTPUT_JOURNAL_AND_CONSOLE:
r = connect_logger_as(unit, context, params, o, ident, fileno, uid, gid);
if (r < 0) {
- log_unit_warning_errno(unit, r, "Failed to connect %s to the journal socket, ignoring: %m", fileno == STDOUT_FILENO ? "stdout" : "stderr");
+ log_unit_warning_errno(unit, r, "Failed to connect %s to the journal socket, ignoring: %m",
+ fileno == STDOUT_FILENO ? "stdout" : "stderr");
r = open_null_as(O_WRONLY, fileno);
} else {
struct stat st;
if (setresuid(uid, uid, uid) < 0)
log_warning_errno(errno, "Failed to setresuid() in sd-pam: %m");
- (void) ignore_signals(SIGPIPE, -1);
+ (void) ignore_signals(SIGPIPE);
/* Wait until our parent died. This will only work if
* the above setresuid() succeeds, otherwise the kernel
assert(p);
assert(ret);
-#define N_ENV_VARS 16
+#define N_ENV_VARS 17
our_env = new0(char*, N_ENV_VARS + _EXEC_DIRECTORY_TYPE_MAX);
if (!our_env)
return -ENOMEM;
our_env[n_env++] = x;
}
+ if (asprintf(&x, "SYSTEMD_EXEC_PID=" PID_FMT, getpid_cached()) < 0)
+ return -ENOMEM;
+
+ our_env[n_env++] = x;
+
our_env[n_env++] = NULL;
assert(n_env <= N_ENV_VARS + _EXEC_DIRECTORY_TYPE_MAX);
#undef N_ENV_VARS
return 0;
}
-static bool exec_needs_mount_namespace(
+bool exec_needs_mount_namespace(
const ExecContext *context,
const ExecParameters *params,
const ExecRuntime *runtime) {
assert(context);
- assert(params);
if (context->root_image)
return true;
if (!strv_isempty(context->read_write_paths) ||
!strv_isempty(context->read_only_paths) ||
- !strv_isempty(context->inaccessible_paths))
+ !strv_isempty(context->inaccessible_paths) ||
+ !strv_isempty(context->exec_paths) ||
+ !strv_isempty(context->no_exec_paths))
return true;
if (context->n_bind_mounts > 0)
if (context->n_mount_images > 0)
return true;
+ if (context->n_extension_images > 0)
+ return true;
+
if (!IN_SET(context->mount_flags, 0, MS_SHARED))
return true;
context->protect_kernel_logs ||
context->protect_control_groups ||
context->protect_proc != PROTECT_PROC_DEFAULT ||
- context->proc_subset != PROC_SUBSET_ALL)
+ context->proc_subset != PROC_SUBSET_ALL ||
+ context->private_ipc ||
+ context->ipc_namespace_path)
return true;
if (context->root_directory) {
return true;
for (ExecDirectoryType t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) {
- if (!params->prefix[t])
+ if (params && !params->prefix[t])
continue;
if (!strv_isempty(context->directories[t].paths))
* user can no longer chmod() the file to gain write access. */
return r;
- if (fchown(fd, uid, (gid_t) -1) < 0)
+ if (fchown(fd, uid, GID_INVALID) < 0)
return -errno;
}
}
if (!ownership_ok)
return r;
- if (fchown(dfd, uid, (gid_t) -1) < 0)
+ if (fchown(dfd, uid, GID_INVALID) < 0)
return -errno;
}
}
_cleanup_strv_free_ char **empty_directories = NULL;
const char *tmp_dir = NULL, *var_tmp_dir = NULL;
const char *root_dir = NULL, *root_image = NULL;
- _cleanup_free_ char *creds_path = NULL;
+ _cleanup_free_ char *creds_path = NULL, *incoming_dir = NULL, *propagate_dir = NULL;
NamespaceInfo ns_info;
bool needs_sandboxing;
BindMount *bind_mounts = NULL;
.protect_system = context->protect_system,
.protect_proc = context->protect_proc,
.proc_subset = context->proc_subset,
+ .private_ipc = context->private_ipc || context->ipc_namespace_path,
};
} else if (!context->dynamic_user && root_dir)
/*
if (context->mount_flags == MS_SHARED)
log_unit_debug(u, "shared mount propagation hidden by other fs namespacing unit settings: ignoring");
- if (exec_context_has_credentials(context) && params->prefix[EXEC_DIRECTORY_RUNTIME]) {
+ if (exec_context_has_credentials(context) &&
+ params->prefix[EXEC_DIRECTORY_RUNTIME] &&
+ FLAGS_SET(params->flags, EXEC_WRITE_CREDENTIALS)) {
creds_path = path_join(params->prefix[EXEC_DIRECTORY_RUNTIME], "credentials", u->id);
if (!creds_path) {
r = -ENOMEM;
}
}
+ if (MANAGER_IS_SYSTEM(u->manager)) {
+ propagate_dir = path_join("/run/systemd/propagate/", u->id);
+ if (!propagate_dir) {
+ r = -ENOMEM;
+ goto finalize;
+ }
+
+ incoming_dir = strdup("/run/systemd/incoming");
+ if (!incoming_dir) {
+ r = -ENOMEM;
+ goto finalize;
+ }
+ }
+
r = setup_namespace(root_dir, root_image, context->root_image_options,
&ns_info, context->read_write_paths,
needs_sandboxing ? context->read_only_paths : NULL,
needs_sandboxing ? context->inaccessible_paths : NULL,
+ needs_sandboxing ? context->exec_paths : NULL,
+ needs_sandboxing ? context->no_exec_paths : NULL,
empty_directories,
bind_mounts,
n_bind_mounts,
context->root_hash, context->root_hash_size, context->root_hash_path,
context->root_hash_sig, context->root_hash_sig_size, context->root_hash_sig_path,
context->root_verity,
+ context->extension_images,
+ context->n_extension_images,
+ propagate_dir,
+ incoming_dir,
+ root_dir || root_image ? params->notify_socket : NULL,
DISSECT_IMAGE_DISCARD_ON_LOOP|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK,
error_path);
n_dont_close += n_fds;
}
- if (runtime)
+ if (runtime) {
append_socket_pair(dont_close, &n_dont_close, runtime->netns_storage_socket);
+ append_socket_pair(dont_close, &n_dont_close, runtime->ipcns_storage_socket);
+ }
if (dcreds) {
if (dcreds->user)
rename_process_from_path(command->path);
- /* We reset exactly these signals, since they are the
- * only ones we set to SIG_IGN in the main daemon. All
- * others we leave untouched because we set them to
- * SIG_DFL or a valid handler initially, both of which
- * will be demoted to SIG_DFL. */
+ /* We reset exactly these signals, since they are the only ones we set to SIG_IGN in the main
+ * daemon. All others we leave untouched because we set them to SIG_DFL or a valid handler initially,
+ * both of which will be demoted to SIG_DFL. */
(void) default_signals(SIGNALS_CRASH_HANDLER,
- SIGNALS_IGNORE, -1);
+ SIGNALS_IGNORE);
if (context->ignore_sigpipe)
- (void) ignore_signals(SIGPIPE, -1);
+ (void) ignore_signals(SIGPIPE);
r = reset_signal_mask();
if (r < 0) {
}
if (context->network_namespace_path && runtime && runtime->netns_storage_socket[0] >= 0) {
- r = open_netns_path(runtime->netns_storage_socket, context->network_namespace_path);
+ r = open_shareable_ns_path(runtime->netns_storage_socket, context->network_namespace_path, CLONE_NEWNET);
if (r < 0) {
*exit_status = EXIT_NETWORK;
return log_unit_error_errno(unit, r, "Failed to open network namespace path %s: %m", context->network_namespace_path);
}
}
+ if (context->ipc_namespace_path && runtime && runtime->ipcns_storage_socket[0] >= 0) {
+ r = open_shareable_ns_path(runtime->ipcns_storage_socket, context->ipc_namespace_path, CLONE_NEWIPC);
+ if (r < 0) {
+ *exit_status = EXIT_NAMESPACE;
+ return log_unit_error_errno(unit, r, "Failed to open IPC namespace path %s: %m", context->ipc_namespace_path);
+ }
+ }
+
r = setup_input(context, params, socket_fd, named_iofds);
if (r < 0) {
*exit_status = EXIT_STDIN;
if ((context->private_network || context->network_namespace_path) && runtime && runtime->netns_storage_socket[0] >= 0) {
if (ns_type_supported(NAMESPACE_NET)) {
- r = setup_netns(runtime->netns_storage_socket);
+ r = setup_shareable_ns(runtime->netns_storage_socket, CLONE_NEWNET);
if (r == -EPERM)
log_unit_warning_errno(unit, r,
"PrivateNetwork=yes is configured, but network namespace setup failed, ignoring: %m");
log_unit_warning(unit, "PrivateNetwork=yes is configured, but the kernel does not support network namespaces, ignoring.");
}
+ if ((context->private_ipc || context->ipc_namespace_path) && runtime && runtime->ipcns_storage_socket[0] >= 0) {
+
+ if (ns_type_supported(NAMESPACE_IPC)) {
+ r = setup_shareable_ns(runtime->ipcns_storage_socket, CLONE_NEWIPC);
+ if (r == -EPERM)
+ log_unit_warning_errno(unit, r,
+ "PrivateIPC=yes is configured, but IPC namespace setup failed, ignoring: %m");
+ else if (r < 0) {
+ *exit_status = EXIT_NAMESPACE;
+ return log_unit_error_errno(unit, r, "Failed to set up IPC namespacing: %m");
+ }
+ } else if (context->ipc_namespace_path) {
+ *exit_status = EXIT_NAMESPACE;
+ return log_unit_error_errno(unit, SYNTHETIC_ERRNO(EOPNOTSUPP),
+ "IPCNamespacePath= is not supported, refusing.");
+ } else
+ log_unit_warning(unit, "PrivateIPC=yes is configured, but the kernel does not support IPC namespaces, ignoring.");
+ }
+
needs_mount_namespace = exec_needs_mount_namespace(context, params, runtime);
if (needs_mount_namespace) {
_cleanup_free_ char *error_path = NULL;
#endif
/* We repeat the fd closing here, to make sure that nothing is leaked from the PAM modules. Note that we are
- * more aggressive this time since socket_fd and the netns fds we don't need anymore. We do keep the exec_fd
+ * more aggressive this time since socket_fd and the netns and ipcns fds we don't need anymore. We do keep the exec_fd
* however if we have it as we want to keep it open until the final execve(). */
r = close_all_fds(keep_fds, n_keep_fds);
r = cg_create(SYSTEMD_CGROUP_CONTROLLER, subcgroup_path);
if (r < 0)
return log_unit_error_errno(unit, r, "Failed to create control group '%s': %m", subcgroup_path);
+
+ /* Normally we would not propagate the oomd xattrs to children but since we created this
+ * sub-cgroup internally we should do it. */
+ cgroup_oomd_xattr_apply(unit, subcgroup_path);
}
}
c->root_hash_sig_size = 0;
c->root_hash_sig_path = mfree(c->root_hash_sig_path);
c->root_verity = mfree(c->root_verity);
+ c->extension_images = mount_image_free_many(c->extension_images, &c->n_extension_images);
c->tty_path = mfree(c->tty_path);
c->syslog_identifier = mfree(c->syslog_identifier);
c->user = mfree(c->user);
c->read_only_paths = strv_free(c->read_only_paths);
c->read_write_paths = strv_free(c->read_write_paths);
c->inaccessible_paths = strv_free(c->inaccessible_paths);
+ c->exec_paths = strv_free(c->exec_paths);
+ c->no_exec_paths = strv_free(c->no_exec_paths);
bind_mount_free_many(c->bind_mounts, c->n_bind_mounts);
c->bind_mounts = NULL;
}
void exec_command_done_array(ExecCommand *c, size_t n) {
- size_t i;
-
- for (i = 0; i < n; i++)
+ for (size_t i = 0; i < n; i++)
exec_command_done(c+i);
}
fprintf(f, " %s", *g);
}
+static void strv_dump(FILE* f, const char *prefix, const char *name, char **strv) {
+ assert(f);
+ assert(prefix);
+ assert(name);
+
+ if (!strv_isempty(strv)) {
+ fprintf(f, "%s%s:", name, prefix);
+ strv_fprintf(f, strv);
+ fputs("\n", f);
+ }
+}
+
void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
char **e, **d, buf_clean[FORMAT_TIMESPAN_MAX];
int r;
fprintf(f, "%sDynamicUser: %s\n", prefix, yes_no(c->dynamic_user));
- if (!strv_isempty(c->supplementary_groups)) {
- fprintf(f, "%sSupplementaryGroups:", prefix);
- strv_fprintf(f, c->supplementary_groups);
- fputs("\n", f);
- }
+ strv_dump(f, prefix, "SupplementaryGroups", c->supplementary_groups);
if (c->pam_name)
fprintf(f, "%sPAMName: %s\n", prefix, c->pam_name);
- if (!strv_isempty(c->read_write_paths)) {
- fprintf(f, "%sReadWritePaths:", prefix);
- strv_fprintf(f, c->read_write_paths);
- fputs("\n", f);
- }
-
- if (!strv_isempty(c->read_only_paths)) {
- fprintf(f, "%sReadOnlyPaths:", prefix);
- strv_fprintf(f, c->read_only_paths);
- fputs("\n", f);
- }
-
- if (!strv_isempty(c->inaccessible_paths)) {
- fprintf(f, "%sInaccessiblePaths:", prefix);
- strv_fprintf(f, c->inaccessible_paths);
- fputs("\n", f);
- }
+ strv_dump(f, prefix, "ReadWritePaths", c->read_write_paths);
+ strv_dump(f, prefix, "ReadOnlyPaths", c->read_only_paths);
+ strv_dump(f, prefix, "InaccessiblePaths", c->inaccessible_paths);
+ strv_dump(f, prefix, "ExecPaths", c->exec_paths);
+ strv_dump(f, prefix, "NoExecPaths", c->no_exec_paths);
for (size_t i = 0; i < c->n_bind_mounts; i++)
fprintf(f, "%s%s: %s%s:%s:%s\n", prefix,
for (size_t i = 0; i < c->n_mount_images; i++) {
MountOptions *o;
- fprintf(f, "%sMountImages: %s%s:%s%s", prefix,
+ fprintf(f, "%sMountImages: %s%s:%s", prefix,
c->mount_images[i].ignore_enoent ? "-": "",
c->mount_images[i].source,
- c->mount_images[i].destination,
- LIST_IS_EMPTY(c->mount_images[i].mount_options) ? "": ":");
+ c->mount_images[i].destination);
LIST_FOREACH(mount_options, o, c->mount_images[i].mount_options)
- fprintf(f, "%s:%s",
+ fprintf(f, ":%s:%s",
partition_designator_to_string(o->partition_designator),
- o->options);
+ strempty(o->options));
+ fprintf(f, "\n");
+ }
+
+ for (size_t i = 0; i < c->n_extension_images; i++) {
+ MountOptions *o;
+
+ fprintf(f, "%sExtensionImages: %s%s", prefix,
+ c->extension_images[i].ignore_enoent ? "-": "",
+ c->extension_images[i].source);
+ LIST_FOREACH(mount_options, o, c->extension_images[i].mount_options)
+ fprintf(f, ":%s:%s",
+ partition_designator_to_string(o->partition_designator),
+ strempty(o->options));
fprintf(f, "\n");
}
}
rt->tmp_dir = mfree(rt->tmp_dir);
rt->var_tmp_dir = mfree(rt->var_tmp_dir);
safe_close_pair(rt->netns_storage_socket);
+ safe_close_pair(rt->ipcns_storage_socket);
return mfree(rt);
}
*n = (ExecRuntime) {
.id = TAKE_PTR(id_copy),
.netns_storage_socket = { -1, -1 },
+ .ipcns_storage_socket = { -1, -1 },
};
*ret = n;
char **tmp_dir,
char **var_tmp_dir,
int netns_storage_socket[2],
+ int ipcns_storage_socket[2],
ExecRuntime **ret) {
_cleanup_(exec_runtime_freep) ExecRuntime *rt = NULL;
assert(m);
assert(id);
- /* tmp_dir, var_tmp_dir, netns_storage_socket fds are donated on success */
-
- r = hashmap_ensure_allocated(&m->exec_runtime_by_id, &string_hash_ops);
- if (r < 0)
- return r;
+ /* tmp_dir, var_tmp_dir, {net,ipc}ns_storage_socket fds are donated on success */
r = exec_runtime_allocate(&rt, id);
if (r < 0)
return r;
- r = hashmap_put(m->exec_runtime_by_id, rt->id, rt);
+ r = hashmap_ensure_put(&m->exec_runtime_by_id, &string_hash_ops, rt->id, rt);
if (r < 0)
return r;
rt->netns_storage_socket[1] = TAKE_FD(netns_storage_socket[1]);
}
+ if (ipcns_storage_socket) {
+ rt->ipcns_storage_socket[0] = TAKE_FD(ipcns_storage_socket[0]);
+ rt->ipcns_storage_socket[1] = TAKE_FD(ipcns_storage_socket[1]);
+ }
+
rt->manager = m;
if (ret)
ExecRuntime **ret) {
_cleanup_(namespace_cleanup_tmpdirp) char *tmp_dir = NULL, *var_tmp_dir = NULL;
- _cleanup_close_pair_ int netns_storage_socket[2] = { -1, -1 };
+ _cleanup_close_pair_ int netns_storage_socket[2] = { -1, -1 }, ipcns_storage_socket[2] = { -1, -1 };
int r;
assert(m);
assert(id);
/* It is not necessary to create ExecRuntime object. */
- if (!c->private_network && !c->private_tmp && !c->network_namespace_path) {
+ if (!c->private_network && !c->private_ipc && !c->private_tmp && !c->network_namespace_path) {
*ret = NULL;
return 0;
}
return -errno;
}
- r = exec_runtime_add(m, id, &tmp_dir, &var_tmp_dir, netns_storage_socket, ret);
+ if (c->private_ipc || c->ipc_namespace_path) {
+ if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, ipcns_storage_socket) < 0)
+ return -errno;
+ }
+
+ r = exec_runtime_add(m, id, &tmp_dir, &var_tmp_dir, netns_storage_socket, ipcns_storage_socket, ret);
if (r < 0)
return r;
fprintf(f, " netns-socket-1=%i", copy);
}
+ if (rt->ipcns_storage_socket[0] >= 0) {
+ int copy;
+
+ copy = fdset_put_dup(fds, rt->ipcns_storage_socket[0]);
+ if (copy < 0)
+ return copy;
+
+ fprintf(f, " ipcns-socket-0=%i", copy);
+ }
+
+ if (rt->ipcns_storage_socket[1] >= 0) {
+ int copy;
+
+ copy = fdset_put_dup(fds, rt->ipcns_storage_socket[1]);
+ if (copy < 0)
+ return copy;
+
+ fprintf(f, " ipcns-socket-1=%i", copy);
+ }
+
fputc('\n', f);
}
safe_close(rt->netns_storage_socket[1]);
rt->netns_storage_socket[1] = fdset_remove(fds, fd);
+
+ } else if (streq(key, "ipcns-socket-0")) {
+ int fd;
+
+ if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd)) {
+ log_unit_debug(u, "Failed to parse ipcns socket value: %s", value);
+ return 0;
+ }
+
+ safe_close(rt->ipcns_storage_socket[0]);
+ rt->ipcns_storage_socket[0] = fdset_remove(fds, fd);
+
+ } else if (streq(key, "ipcns-socket-1")) {
+ int fd;
+
+ if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd)) {
+ log_unit_debug(u, "Failed to parse ipcns socket value: %s", value);
+ return 0;
+ }
+
+ safe_close(rt->ipcns_storage_socket[1]);
+ rt->ipcns_storage_socket[1] = fdset_remove(fds, fd);
} else
return 0;
int exec_runtime_deserialize_one(Manager *m, const char *value, FDSet *fds) {
_cleanup_free_ char *tmp_dir = NULL, *var_tmp_dir = NULL;
char *id = NULL;
- int r, fdpair[] = {-1, -1};
+ int r, netns_fdpair[] = {-1, -1}, ipcns_fdpair[] = {-1, -1};
const char *p, *v = value;
size_t n;
n = strcspn(v, " ");
buf = strndupa(v, n);
- r = safe_atoi(buf, &fdpair[0]);
+ r = safe_atoi(buf, &netns_fdpair[0]);
if (r < 0)
return log_debug_errno(r, "Unable to parse exec-runtime specification netns-socket-0=%s: %m", buf);
- if (!fdset_contains(fds, fdpair[0]))
+ if (!fdset_contains(fds, netns_fdpair[0]))
return log_debug_errno(SYNTHETIC_ERRNO(EBADF),
- "exec-runtime specification netns-socket-0= refers to unknown fd %d: %m", fdpair[0]);
- fdpair[0] = fdset_remove(fds, fdpair[0]);
+ "exec-runtime specification netns-socket-0= refers to unknown fd %d: %m", netns_fdpair[0]);
+ netns_fdpair[0] = fdset_remove(fds, netns_fdpair[0]);
if (v[n] != ' ')
goto finalize;
p = v + n + 1;
n = strcspn(v, " ");
buf = strndupa(v, n);
- r = safe_atoi(buf, &fdpair[1]);
+
+ r = safe_atoi(buf, &netns_fdpair[1]);
if (r < 0)
return log_debug_errno(r, "Unable to parse exec-runtime specification netns-socket-1=%s: %m", buf);
- if (!fdset_contains(fds, fdpair[1]))
+ if (!fdset_contains(fds, netns_fdpair[1]))
+ return log_debug_errno(SYNTHETIC_ERRNO(EBADF),
+ "exec-runtime specification netns-socket-1= refers to unknown fd %d: %m", netns_fdpair[1]);
+ netns_fdpair[1] = fdset_remove(fds, netns_fdpair[1]);
+ if (v[n] != ' ')
+ goto finalize;
+ p = v + n + 1;
+ }
+
+ v = startswith(p, "ipcns-socket-0=");
+ if (v) {
+ char *buf;
+
+ n = strcspn(v, " ");
+ buf = strndupa(v, n);
+
+ r = safe_atoi(buf, &ipcns_fdpair[0]);
+ if (r < 0)
+ return log_debug_errno(r, "Unable to parse exec-runtime specification ipcns-socket-0=%s: %m", buf);
+ if (!fdset_contains(fds, ipcns_fdpair[0]))
+ return log_debug_errno(SYNTHETIC_ERRNO(EBADF),
+ "exec-runtime specification ipcns-socket-0= refers to unknown fd %d: %m", ipcns_fdpair[0]);
+ ipcns_fdpair[0] = fdset_remove(fds, ipcns_fdpair[0]);
+ if (v[n] != ' ')
+ goto finalize;
+ p = v + n + 1;
+ }
+
+ v = startswith(p, "ipcns-socket-1=");
+ if (v) {
+ char *buf;
+
+ n = strcspn(v, " ");
+ buf = strndupa(v, n);
+
+ r = safe_atoi(buf, &ipcns_fdpair[1]);
+ if (r < 0)
+ return log_debug_errno(r, "Unable to parse exec-runtime specification ipcns-socket-1=%s: %m", buf);
+ if (!fdset_contains(fds, ipcns_fdpair[1]))
return log_debug_errno(SYNTHETIC_ERRNO(EBADF),
- "exec-runtime specification netns-socket-1= refers to unknown fd %d: %m", fdpair[1]);
- fdpair[1] = fdset_remove(fds, fdpair[1]);
+ "exec-runtime specification ipcns-socket-1= refers to unknown fd %d: %m", ipcns_fdpair[1]);
+ ipcns_fdpair[1] = fdset_remove(fds, ipcns_fdpair[1]);
}
finalize:
- r = exec_runtime_add(m, id, &tmp_dir, &var_tmp_dir, fdpair, NULL);
+ r = exec_runtime_add(m, id, &tmp_dir, &var_tmp_dir, netns_fdpair, ipcns_fdpair, NULL);
if (r < 0)
return log_debug_errno(r, "Failed to add exec-runtime: %m");
return 0;