From: Lennart Poettering Date: Thu, 7 Mar 2019 15:39:01 +0000 (+0100) Subject: core: add new setting NetworkNamespacePath= for configuring a netns by path for a... X-Git-Tag: v242-rc1~158^2~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a8d08f39d140afb1cb047c65d7d24388bda82e71;p=thirdparty%2Fsystemd.git core: add new setting NetworkNamespacePath= for configuring a netns by path for a service Fixes: #2741 --- diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index f22bf4a371c..0b28643e791 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -778,6 +778,7 @@ const sd_bus_vtable bus_exec_vtable[] = { SD_BUS_PROPERTY("MountAPIVFS", "b", bus_property_get_bool, offsetof(ExecContext, mount_apivfs), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("KeyringMode", "s", property_get_exec_keyring_mode, offsetof(ExecContext, keyring_mode), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ProtectHostname", "b", bus_property_get_bool, offsetof(ExecContext, protect_hostname), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("NetworkNamespacePath", "s", NULL, offsetof(ExecContext, network_namespace_path), SD_BUS_VTABLE_PROPERTY_CONST), /* Obsolete/redundant properties: */ SD_BUS_PROPERTY("Capabilities", "s", property_get_empty_string, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), @@ -1217,6 +1218,9 @@ int bus_exec_context_set_transient_property( if (streq(name, "MountFlags")) return bus_set_transient_mount_flags(u, name, &c->mount_flags, message, flags, error); + if (streq(name, "NetworkNamespacePath")) + return bus_set_transient_path(u, name, &c->network_namespace_path, message, flags, error); + if (streq(name, "SupplementaryGroups")) { _cleanup_strv_free_ char **l = NULL; char **p; diff --git a/src/core/execute.c b/src/core/execute.c index 4a0ffe198a2..240ec5487b2 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -3062,6 +3062,14 @@ static int exec_child( } } + if (context->network_namespace_path && runtime && runtime->netns_storage_socket[0] >= 0) { + r = open_netns_path(runtime->netns_storage_socket, context->network_namespace_path); + 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); + } + } + r = setup_input(context, params, socket_fd, named_iofds); if (r < 0) { *exit_status = EXIT_STDIN; @@ -3272,13 +3280,17 @@ static int exec_child( } } - if (context->private_network && runtime && runtime->netns_storage_socket[0] >= 0) { + 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); if (r < 0) { *exit_status = EXIT_NETWORK; return log_unit_error_errno(unit, r, "Failed to set up network namespacing: %m"); } + } else if (context->network_namespace_path) { + *exit_status = EXIT_NETWORK; + return log_unit_error_errno(unit, SYNTHETIC_ERRNO(EOPNOTSUPP), "NetworkNamespacePath= is not supported, refusing."); } else log_unit_warning(unit, "PrivateNetwork=yes is configured, but the kernel does not support network namespaces, ignoring."); } @@ -3879,6 +3891,8 @@ void exec_context_done(ExecContext *c) { c->stdin_data = mfree(c->stdin_data); c->stdin_data_size = 0; + + c->network_namespace_path = mfree(c->network_namespace_path); } int exec_context_destroy_runtime_directory(const ExecContext *c, const char *runtime_prefix) { @@ -4556,6 +4570,11 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { prefix, s); } + if (c->network_namespace_path) + fprintf(f, + "%sNetworkNamespacePath: %s\n", + prefix, c->network_namespace_path); + if (c->syscall_errno > 0) { const char *errno_name; @@ -4947,7 +4966,7 @@ static int exec_runtime_make(Manager *m, const ExecContext *c, const char *id, E assert(id); /* It is not necessary to create ExecRuntime object. */ - if (!c->private_network && !c->private_tmp) + if (!c->private_network && !c->private_tmp && !c->network_namespace_path) return 0; if (c->private_tmp) { @@ -4956,7 +4975,7 @@ static int exec_runtime_make(Manager *m, const ExecContext *c, const char *id, E return r; } - if (c->private_network) { + if (c->private_network || c->network_namespace_path) { if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, netns_storage_socket) < 0) return -errno; } diff --git a/src/core/execute.h b/src/core/execute.h index 4b5b2d98cef..df6dd9f3886 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -279,6 +279,8 @@ struct ExecContext { bool nice_set:1; bool ioprio_set:1; bool cpu_sched_set:1; + + char *network_namespace_path; }; static inline bool exec_context_restrict_namespaces_set(const ExecContext *c) { diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 2ac822ef4b2..c7c097d0a4a 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -114,6 +114,7 @@ $1.PrivateDevices, config_parse_bool, 0, $1.ProtectKernelTunables, config_parse_bool, 0, offsetof($1, exec_context.protect_kernel_tunables) $1.ProtectKernelModules, config_parse_bool, 0, offsetof($1, exec_context.protect_kernel_modules) $1.ProtectControlGroups, config_parse_bool, 0, offsetof($1, exec_context.protect_control_groups) +$1.NetworkNamespacePath, config_parse_unit_path_printf, 0, offsetof($1, exec_context.network_namespace_path) $1.PrivateNetwork, config_parse_bool, 0, offsetof($1, exec_context.private_network) $1.PrivateUsers, config_parse_bool, 0, offsetof($1, exec_context.private_users) $1.PrivateMounts, config_parse_bool, 0, offsetof($1, exec_context.private_mounts)