diff options
author | Sergiusz Urbaniak <sergiusz.urbaniak@gmail.com> | 2016-10-14 14:00:15 +0200 |
---|---|---|
committer | Sergiusz Urbaniak <sergiusz.urbaniak@gmail.com> | 2016-11-18 09:50:40 +0100 |
commit | 4f086aab52812472a24c9b8b627589880a38696e (patch) | |
tree | 22fd04bdbb8346cbfda4201627eabf57c5b9ce51 /src/nspawn/nspawn.c | |
parent | 843d5baf6aad6c53fc00ea8d95d83209a4f92de1 (diff) |
nspawn: R/W support for /sys, and /proc/sys
This commit adds the possibility to leave /sys, and /proc/sys read-write.
It introduces a new (undocumented) env var SYSTEMD_NSPAWN_API_VFS_WRITABLE
to enable this feature.
If set to "yes", /sys, and /proc/sys will be read-write.
If set to "no", /sys, and /proc/sys will be read-only.
If set to "network" /proc/sys/net will be read-write. This is useful in
use-cases, where systemd-nspawn is used in an external network
namespace.
This adds the possibility to start privileged containers which need more
control over settings in the /proc, and /sys filesystem.
This is also a follow-up on the discussion from
https://github.com/systemd/systemd/pull/4018#r76971862 where an
introduction of a simple env var to enable R/W support for those
directories was already discussed.
Diffstat (limited to 'src/nspawn/nspawn.c')
-rw-r--r-- | src/nspawn/nspawn.c | 53 |
1 files changed, 46 insertions, 7 deletions
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 9b9ae909c9..69b9efe320 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -195,6 +195,7 @@ static const char *arg_container_service_name = "systemd-nspawn"; static bool arg_notify_ready = false; static bool arg_use_cgns = true; static unsigned long arg_clone_ns_flags = CLONE_NEWIPC|CLONE_NEWPID|CLONE_NEWUTS; +static MountSettingsMask arg_mount_settings = MOUNT_APPLY_APIVFS_RO; static void help(void) { printf("%s [OPTIONS...] [PATH] [ARGUMENTS...]\n\n" @@ -378,6 +379,31 @@ static void parse_share_ns_env(const char *name, unsigned long ns_flag) { arg_clone_ns_flags = (arg_clone_ns_flags & ~ns_flag) | (r > 0 ? 0 : ns_flag); } +static void parse_mount_settings_env(void) { + int r; + const char *e; + + e = getenv("SYSTEMD_NSPAWN_API_VFS_WRITABLE"); + if (!e) + return; + + if (streq(e, "network")) { + arg_mount_settings |= MOUNT_APPLY_APIVFS_RO|MOUNT_APPLY_APIVFS_NETNS; + return; + } + + r = parse_boolean(e); + if (r < 0) { + log_warning_errno(r, "Failed to parse SYSTEMD_NSPAWN_API_VFS_WRITABLE from environment, ignoring."); + return; + } else if (r > 0) + arg_mount_settings &= ~MOUNT_APPLY_APIVFS_RO; + else + arg_mount_settings |= MOUNT_APPLY_APIVFS_RO; + + arg_mount_settings &= ~MOUNT_APPLY_APIVFS_NETNS; +} + static int parse_argv(int argc, char *argv[]) { enum { @@ -1070,6 +1096,14 @@ static int parse_argv(int argc, char *argv[]) { parse_share_ns_env("SYSTEMD_NSPAWN_SHARE_NS_UTS", CLONE_NEWUTS); parse_share_ns_env("SYSTEMD_NSPAWN_SHARE_SYSTEM", CLONE_NEWIPC|CLONE_NEWPID|CLONE_NEWUTS); + if (arg_userns_mode != USER_NAMESPACE_NO) + arg_mount_settings |= MOUNT_USE_USERNS; + + if (arg_private_network) + arg_mount_settings |= MOUNT_APPLY_APIVFS_NETNS; + + parse_mount_settings_env(); + if (!(arg_clone_ns_flags & CLONE_NEWPID) || !(arg_clone_ns_flags & CLONE_NEWUTS)) { arg_register = false; @@ -1164,6 +1198,15 @@ static int parse_argv(int argc, char *argv[]) { } static int verify_arguments(void) { + if (arg_userns_mode != USER_NAMESPACE_NO && (arg_mount_settings & MOUNT_APPLY_APIVFS_NETNS) && !arg_private_network) { + log_error("Invalid namespacing settings. Mounting sysfs with --private-users requires --private-network."); + return -EINVAL; + } + + if (arg_userns_mode != USER_NAMESPACE_NO && !(arg_mount_settings & MOUNT_APPLY_APIVFS_RO)) { + log_error("Cannot combine --private-users with read-write mounts."); + return -EINVAL; + } if (arg_volatile_mode != VOLATILE_NO && arg_read_only) { log_error("Cannot combine --read-only with --volatile. Note that --volatile already implies a read-only base hierarchy."); @@ -2700,9 +2743,7 @@ static int inner_child( return log_error_errno(r, "Couldn't become new root: %m"); r = mount_all(NULL, - arg_userns_mode != USER_NAMESPACE_NO, - true, - arg_private_network, + arg_mount_settings | MOUNT_IN_USERNS, arg_uid_shift, arg_uid_range, arg_selinux_apifs_context); @@ -2710,7 +2751,7 @@ static int inner_child( if (r < 0) return r; - r = mount_sysfs(NULL); + r = mount_sysfs(NULL, arg_mount_settings); if (r < 0) return r; @@ -3077,9 +3118,7 @@ static int outer_child( } r = mount_all(directory, - arg_userns_mode != USER_NAMESPACE_NO, - false, - arg_private_network, + arg_mount_settings, arg_uid_shift, arg_uid_range, arg_selinux_apifs_context); |