]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #4395 from s-urbaniak/rw-support
authorLennart Poettering <lennart@poettering.net>
Fri, 18 Nov 2016 11:36:46 +0000 (12:36 +0100)
committerGitHub <noreply@github.com>
Fri, 18 Nov 2016 11:36:46 +0000 (12:36 +0100)
nspawn: R/W support for /sysfs, /proc, and /proc/sys/net

1  2 
src/nspawn/nspawn.c

diff --combined src/nspawn/nspawn.c
index 50d8aa049c78ad88ffcd0f1478015d70880e0d2b,69b9efe320e15b466f6485f0bcdc8383054f1d85..a6adbbe879d137f5120a80a9acdfaf513794ce70
   * the init process in the container pid can send messages to nspawn following the sd_notify(3) protocol */
  #define NSPAWN_NOTIFY_SOCKET_PATH "/run/systemd/nspawn/notify"
  
 +#define EXIT_FORCE_RESTART 133
 +
  typedef enum ContainerStatus {
          CONTAINER_TERMINATED,
          CONTAINER_REBOOTED
@@@ -197,6 -195,7 +197,7 @@@ static const char *arg_container_servic
  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"
@@@ -380,6 -379,31 +381,31 @@@ static void parse_share_ns_env(const ch
          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 {
          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;
  }
  
  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.");
@@@ -2702,9 -2743,7 +2745,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);
          if (r < 0)
                  return r;
  
-         r = mount_sysfs(NULL);
+         r = mount_sysfs(NULL, arg_mount_settings);
          if (r < 0)
                  return r;
  
@@@ -3079,9 -3118,7 +3120,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);
@@@ -4004,7 -4041,7 +4043,7 @@@ static int run(int master
                   *         because 133 is special-cased in the service file to reboot the container.
                   * otherwise → The container exited with zero status and a reboot was not requested.
                   */
 -                if (r == 133)
 +                if (r == EXIT_FORCE_RESTART)
                          r = EXIT_FAILURE; /* replace 133 with the general failure code */
                  *ret = r;
                  return 0; /* finito */
                   * file uses RestartForceExitStatus=133 so that this results in a full
                   * nspawn restart. This is necessary since we might have cgroup parameters
                   * set we want to have flushed out. */
 -                *ret = 0;
 -                return 133;
 +                *ret = EXIT_FORCE_RESTART;
 +                return 0; /* finito */
          }
  
          expose_port_flush(arg_expose_ports, exposed);
@@@ -4278,8 -4315,8 +4317,8 @@@ int main(int argc, char *argv[]) 
  
  finish:
          sd_notify(false,
 -                  "STOPPING=1\n"
 -                  "STATUS=Terminating...");
 +                  r == 0 && ret == EXIT_FORCE_RESTART ? "STOPPING=1\nSTATUS=Restarting..." :
 +                                                        "STOPPING=1\nSTATUS=Terminating...");
  
          if (pid > 0)
                  kill(pid, SIGKILL);