diff options
author | Xℹ Ruoyao <xry111@mengyan1223.wang> | 2021-02-16 16:58:56 +0100 |
---|---|---|
committer | Xℹ Ruoyao <xry111@mengyan1223.wang> | 2021-03-03 17:04:36 +0100 |
commit | a70581ffb5c13c91c76ff73ba6f5f3ff59c5a915 (patch) | |
tree | 1dc596f6e7fee00e6fa1bc7d10dd22ebc131179f /src | |
parent | Refactor network namespace specific functions in generic helpers (diff) | |
download | systemd-a70581ffb5c13c91c76ff73ba6f5f3ff59c5a915.tar.xz systemd-a70581ffb5c13c91c76ff73ba6f5f3ff59c5a915.zip |
New directives PrivateIPC and IPCNamespacePath
Diffstat (limited to 'src')
-rw-r--r-- | src/core/dbus-execute.c | 8 | ||||
-rw-r--r-- | src/core/execute.c | 155 | ||||
-rw-r--r-- | src/core/execute.h | 5 | ||||
-rw-r--r-- | src/core/load-fragment-gperf.gperf.m4 | 2 | ||||
-rw-r--r-- | src/core/socket.c | 8 | ||||
-rw-r--r-- | src/shared/bus-unit-util.c | 2 | ||||
-rw-r--r-- | src/test/test-stat-util.c | 2 |
7 files changed, 165 insertions, 17 deletions
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index a4817ca6de..f474a02b0e 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -1162,6 +1162,7 @@ const sd_bus_vtable bus_exec_vtable[] = { SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PrivateUsers", "b", bus_property_get_bool, offsetof(ExecContext, private_users), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PrivateMounts", "b", bus_property_get_bool, offsetof(ExecContext, private_mounts), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("PrivateIPC", "b", bus_property_get_bool, offsetof(ExecContext, private_ipc), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ProtectHome", "s", property_get_protect_home, offsetof(ExecContext, protect_home), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ProtectSystem", "s", property_get_protect_system, offsetof(ExecContext, protect_system), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST), @@ -1204,6 +1205,7 @@ const sd_bus_vtable bus_exec_vtable[] = { SD_BUS_PROPERTY("ProcSubset", "s", property_get_proc_subset, offsetof(ExecContext, proc_subset), 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), + SD_BUS_PROPERTY("IPCNamespacePath", "s", NULL, offsetof(ExecContext, ipc_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), @@ -1753,6 +1755,9 @@ int bus_exec_context_set_transient_property( if (streq(name, "PrivateNetwork")) return bus_set_transient_bool(u, name, &c->private_network, message, flags, error); + if (streq(name, "PrivateIPC")) + return bus_set_transient_bool(u, name, &c->private_ipc, message, flags, error); + if (streq(name, "PrivateUsers")) return bus_set_transient_bool(u, name, &c->private_users, message, flags, error); @@ -1873,6 +1878,9 @@ int bus_exec_context_set_transient_property( if (streq(name, "NetworkNamespacePath")) return bus_set_transient_path(u, name, &c->network_namespace_path, message, flags, error); + if (streq(name, "IPCNamespacePath")) + return bus_set_transient_path(u, name, &c->ipc_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 0a2d2e1158..684b5a233e 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -3476,8 +3476,10 @@ static int close_remaining_fds( 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) @@ -3925,6 +3927,14 @@ static int exec_child( } } + 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; @@ -4211,6 +4221,25 @@ static int exec_child( 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; @@ -4314,7 +4343,7 @@ static int exec_child( #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); @@ -6057,6 +6086,7 @@ static ExecRuntime* exec_runtime_free(ExecRuntime *rt, bool destroy) { 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); } @@ -6081,6 +6111,7 @@ static int exec_runtime_allocate(ExecRuntime **ret, const char *id) { *n = (ExecRuntime) { .id = TAKE_PTR(id_copy), .netns_storage_socket = { -1, -1 }, + .ipcns_storage_socket = { -1, -1 }, }; *ret = n; @@ -6093,6 +6124,7 @@ static int exec_runtime_add( 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; @@ -6101,7 +6133,7 @@ static int exec_runtime_add( assert(m); assert(id); - /* tmp_dir, var_tmp_dir, netns_storage_socket fds are donated on success */ + /* tmp_dir, var_tmp_dir, {net,ipc}ns_storage_socket fds are donated on success */ r = exec_runtime_allocate(&rt, id); if (r < 0) @@ -6120,6 +6152,11 @@ static int exec_runtime_add( 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) @@ -6136,7 +6173,7 @@ static int exec_runtime_make( 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); @@ -6144,7 +6181,7 @@ static int exec_runtime_make( 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; } @@ -6163,7 +6200,12 @@ static int exec_runtime_make( 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; @@ -6254,6 +6296,26 @@ int exec_runtime_serialize(const Manager *m, FILE *f, FDSet *fds) { 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); } @@ -6335,6 +6397,28 @@ int exec_runtime_deserialize_compat(Unit *u, const char *key, const char *value, 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; @@ -6358,7 +6442,7 @@ int exec_runtime_deserialize_compat(Unit *u, const char *key, const char *value, 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; @@ -6401,13 +6485,13 @@ int exec_runtime_deserialize_one(Manager *m, const char *value, FDSet *fds) { 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; @@ -6419,17 +6503,56 @@ int exec_runtime_deserialize_one(Manager *m, const char *value, FDSet *fds) { 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; diff --git a/src/core/execute.h b/src/core/execute.h index 20e1799b46..4c7a5b874f 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -117,6 +117,9 @@ struct ExecRuntime { /* An AF_UNIX socket pair, that contains a datagram containing a file descriptor referring to the network * namespace. */ int netns_storage_socket[2]; + + /* Like netns_storage_socket, but the file descriptor is referring to the IPC namespace. */ + int ipcns_storage_socket[2]; }; typedef enum ExecDirectoryType { @@ -280,6 +283,7 @@ struct ExecContext { bool private_devices; bool private_users; bool private_mounts; + bool private_ipc; bool protect_kernel_tunables; bool protect_kernel_modules; bool protect_kernel_logs; @@ -314,6 +318,7 @@ struct ExecContext { Set *address_families; char *network_namespace_path; + char *ipc_namespace_path; ExecDirectory directories[_EXEC_DIRECTORY_TYPE_MAX]; ExecPreserveMode runtime_directory_preserve_mode; diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 6a11ef0d9d..21bbcffe41 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -133,10 +133,12 @@ $1.ProtectKernelLogs, config_parse_bool, $1.ProtectClock, config_parse_bool, 0, offsetof($1, exec_context.protect_clock) $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.IPCNamespacePath, config_parse_unit_path_printf, 0, offsetof($1, exec_context.ipc_namespace_path) $1.LogNamespace, config_parse_log_namespace, 0, offsetof($1, exec_context) $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) +$1.PrivateIPC, config_parse_bool, 0, offsetof($1, exec_context.private_ipc) $1.ProtectSystem, config_parse_protect_system, 0, offsetof($1, exec_context.protect_system) $1.ProtectHome, config_parse_protect_home, 0, offsetof($1, exec_context.protect_home) $1.MountFlags, config_parse_exec_mount_flags, 0, offsetof($1, exec_context.mount_flags) diff --git a/src/core/socket.c b/src/core/socket.c index 4bc77f3018..6255e704ce 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -1552,6 +1552,14 @@ static int socket_address_listen_in_cgroup( return log_unit_error_errno(UNIT(s), r, "Failed to open network namespace path %s: %m", s->exec_context.network_namespace_path); } + if (s->exec_context.ipc_namespace_path && + s->exec_runtime && + s->exec_runtime->ipcns_storage_socket[0] >= 0) { + r = open_shareable_ns_path(s->exec_runtime->netns_storage_socket, s->exec_context.network_namespace_path, CLONE_NEWIPC); + if (r < 0) + return log_unit_error_errno(UNIT(s), r, "Failed to open IPC namespace path %s: %m", s->exec_context.ipc_namespace_path); + } + if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, pair) < 0) return log_unit_error_errno(UNIT(s), errno, "Failed to create communication channel: %m"); diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index a58495dbf8..9ed5378791 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -882,6 +882,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con "ProtectProc", "ProcSubset", "NetworkNamespacePath", + "IPCNamespacePath", "LogNamespace")) return bus_append_string(m, field, eq); @@ -894,6 +895,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con "PrivateNetwork", "PrivateUsers", "PrivateMounts", + "PrivateIPC", "NoNewPrivileges", "SyslogLevelPrefix", "MemoryDenyWriteExecute", diff --git a/src/test/test-stat-util.c b/src/test/test-stat-util.c index 7f03db5fa7..4dd18be65c 100644 --- a/src/test/test-stat-util.c +++ b/src/test/test-stat-util.c @@ -2,8 +2,8 @@ #include <fcntl.h> #include <linux/magic.h> -#include <unistd.h> #include <sched.h> +#include <unistd.h> #include "alloc-util.h" #include "fd-util.h" |