]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #15891 from bluca/host_os_release
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 8 Jul 2020 21:52:13 +0000 (23:52 +0200)
committerGitHub <noreply@github.com>
Wed, 8 Jul 2020 21:52:13 +0000 (23:52 +0200)
Container Interface: expose the host's os-release metadata to nspawn and portable guests

1  2 
src/nspawn/nspawn.c
src/portable/portable.c

diff --combined src/nspawn/nspawn.c
index 0f2d01c0aa8872928ff3d1a61e33f92ef9444988,926b76dc11734ad12f735b3682196d4573d0193f..1f321f9ea3f29ef7740b53670d2326862aed936d
@@@ -200,12 -200,9 +200,12 @@@ static unsigned long arg_clone_ns_flag
  static MountSettingsMask arg_mount_settings = MOUNT_APPLY_APIVFS_RO|MOUNT_APPLY_TMPFS_TMP;
  static void *arg_root_hash = NULL;
  static char *arg_verity_data = NULL;
 +static char *arg_root_hash_sig_path = NULL;
 +static void *arg_root_hash_sig = NULL;
 +static size_t arg_root_hash_sig_size = 0;
  static size_t arg_root_hash_size = 0;
 -static char **arg_syscall_whitelist = NULL;
 -static char **arg_syscall_blacklist = NULL;
 +static char **arg_syscall_allow_list = NULL;
 +static char **arg_syscall_deny_list = NULL;
  #if HAVE_SECCOMP
  static scmp_filter_ctx arg_seccomp = NULL;
  #endif
@@@ -247,10 -244,8 +247,10 @@@ STATIC_DESTRUCTOR_REGISTER(arg_property
  STATIC_DESTRUCTOR_REGISTER(arg_parameters, strv_freep);
  STATIC_DESTRUCTOR_REGISTER(arg_root_hash, freep);
  STATIC_DESTRUCTOR_REGISTER(arg_verity_data, freep);
 -STATIC_DESTRUCTOR_REGISTER(arg_syscall_whitelist, strv_freep);
 -STATIC_DESTRUCTOR_REGISTER(arg_syscall_blacklist, strv_freep);
 +STATIC_DESTRUCTOR_REGISTER(arg_root_hash_sig_path, freep);
 +STATIC_DESTRUCTOR_REGISTER(arg_root_hash_sig, freep);
 +STATIC_DESTRUCTOR_REGISTER(arg_syscall_allow_list, strv_freep);
 +STATIC_DESTRUCTOR_REGISTER(arg_syscall_deny_list, strv_freep);
  #if HAVE_SECCOMP
  STATIC_DESTRUCTOR_REGISTER(arg_seccomp, seccomp_releasep);
  #endif
@@@ -310,10 -305,6 +310,10 @@@ static int help(void) 
                 "     --read-only            Mount the root directory read-only\n"
                 "     --volatile[=MODE]      Run the system in volatile mode\n"
                 "     --root-hash=HASH       Specify verity root hash for root disk image\n"
 +               "     --root-hash-sig=SIG    Specify pkcs7 signature of root hash for verity\n"
 +               "                            as a DER encoded PKCS7, either as a path to a file\n"
 +               "                            or as an ASCII base64 encoded string prefixed by\n"
 +               "                            'base64:'\n"
                 "     --verity-data=PATH     Specify hash device for verity\n"
                 "     --pivot-root=PATH[:PATH]\n"
                 "                            Pivot root to given directory in the container\n\n"
@@@ -676,7 -667,6 +676,7 @@@ static int parse_argv(int argc, char *a
                  ARG_OCI_BUNDLE,
                  ARG_NO_PAGER,
                  ARG_VERITY_DATA,
 +                ARG_ROOT_HASH_SIG,
          };
  
          static const struct option options[] = {
                  { "oci-bundle",             required_argument, NULL, ARG_OCI_BUNDLE             },
                  { "no-pager",               no_argument,       NULL, ARG_NO_PAGER               },
                  { "verity-data",            required_argument, NULL, ARG_VERITY_DATA            },
 +                { "root-hash-sig",          required_argument, NULL, ARG_ROOT_HASH_SIG          },
                  {}
          };
  
                                  return r;
                          break;
  
 +                case ARG_ROOT_HASH_SIG: {
 +                        char *value;
 +
 +                        if ((value = startswith(optarg, "base64:"))) {
 +                                void *p;
 +                                size_t l;
 +
 +                                r = unbase64mem(value, strlen(value), &p, &l);
 +                                if (r < 0)
 +                                        return log_error_errno(r, "Failed to parse root hash signature '%s': %m", optarg);
 +
 +                                free_and_replace(arg_root_hash_sig, p);
 +                                arg_root_hash_sig_size = l;
 +                                arg_root_hash_sig_path = mfree(arg_root_hash_sig_path);
 +                        } else {
 +                                r = parse_path_argument_and_warn(optarg, false, &arg_root_hash_sig_path);
 +                                if (r < 0)
 +                                        return r;
 +                                arg_root_hash_sig = mfree(arg_root_hash_sig);
 +                                arg_root_hash_sig_size = 0;
 +                        }
 +
 +                        break;
 +                }
 +
                  case ARG_SYSTEM_CALL_FILTER: {
                          bool negative;
                          const char *items;
                                          return log_error_errno(r, "Failed to parse system call filter: %m");
  
                                  if (negative)
 -                                        r = strv_extend(&arg_syscall_blacklist, word);
 +                                        r = strv_extend(&arg_syscall_deny_list, word);
                                  else
 -                                        r = strv_extend(&arg_syscall_whitelist, word);
 +                                        r = strv_extend(&arg_syscall_allow_list, word);
                                  if (r < 0)
                                          return log_oom();
                          }
@@@ -2211,11 -2175,10 +2211,11 @@@ static int setup_dev_console(const cha
  static int setup_keyring(void) {
          key_serial_t keyring;
  
 -        /* Allocate a new session keyring for the container. This makes sure the keyring of the session systemd-nspawn
 -         * was invoked from doesn't leak into the container. Note that by default we block keyctl() and request_key()
 -         * anyway via seccomp so doing this operation isn't strictly necessary, but in case people explicitly whitelist
 -         * these system calls let's make sure we don't leak anything into the container. */
 +        /* Allocate a new session keyring for the container. This makes sure the keyring of the session
 +         * systemd-nspawn was invoked from doesn't leak into the container. Note that by default we block
 +         * keyctl() and request_key() anyway via seccomp so doing this operation isn't strictly necessary,
 +         * but in case people explicitly allow-list these system calls let's make sure we don't leak anything
 +         * into the container. */
  
          keyring = keyctl(KEYCTL_JOIN_SESSION_KEYRING, 0, 0, 0, 0);
          if (keyring == -1) {
@@@ -2931,7 -2894,8 +2931,8 @@@ static int inner_child
                  int kmsg_socket,
                  int rtnl_socket,
                  int master_pty_socket,
-                 FDSet *fds) {
+                 FDSet *fds,
+                 char **os_release_pairs) {
  
          _cleanup_free_ char *home = NULL;
          char as_uuid[ID128_UUID_STRING_MAX];
          } else
  #endif
          {
 -                r = setup_seccomp(arg_caps_retain, arg_syscall_whitelist, arg_syscall_blacklist);
 +                r = setup_seccomp(arg_caps_retain, arg_syscall_allow_list, arg_syscall_deny_list);
                  if (r < 0)
                          return r;
          }
          if (asprintf((char **)(envp + n_env++), "NOTIFY_SOCKET=%s", NSPAWN_NOTIFY_SOCKET_PATH) < 0)
                  return log_oom();
  
-         env_use = strv_env_merge(2, envp, arg_setenv);
+         env_use = strv_env_merge(3, envp, arg_setenv, os_release_pairs);
          if (!env_use)
                  return log_oom();
  
@@@ -3316,6 -3280,7 +3317,7 @@@ static int outer_child
                  FDSet *fds,
                  int netns_fd) {
  
+         _cleanup_strv_free_ char **os_release_pairs = NULL;
          _cleanup_close_ int fd = -1;
          const char *p;
          pid_t pid;
  
          log_debug("Outer child is initializing.");
  
+         r = load_os_release_pairs_with_prefix("/", "container_host_", &os_release_pairs);
+         if (r < 0)
+                 log_debug_errno(r, "Failed to read os-release from host for container, ignoring: %m");
          if (prctl(PR_SET_PDEATHSIG, SIGKILL) < 0)
                  return log_error_errno(errno, "PR_SET_PDEATHSIG failed: %m");
  
                                  return log_error_errno(r, "Failed to join network namespace: %m");
                  }
  
-                 r = inner_child(barrier, directory, secondary, kmsg_socket, rtnl_socket, master_pty_socket, fds);
+                 r = inner_child(barrier, directory, secondary, kmsg_socket, rtnl_socket, master_pty_socket, fds, os_release_pairs);
                  if (r < 0)
                          _exit(EXIT_FAILURE);
  
@@@ -3991,11 -3960,11 +3997,11 @@@ static int merge_settings(Settings *set
  
          if ((arg_settings_mask & SETTING_SYSCALL_FILTER) == 0) {
  
 -                if (!arg_settings_trusted && !strv_isempty(settings->syscall_whitelist))
 +                if (!arg_settings_trusted && !strv_isempty(settings->syscall_allow_list))
                          log_warning("Ignoring SystemCallFilter= settings, file %s is not trusted.", path);
                  else {
 -                        strv_free_and_replace(arg_syscall_whitelist, settings->syscall_whitelist);
 -                        strv_free_and_replace(arg_syscall_blacklist, settings->syscall_blacklist);
 +                        strv_free_and_replace(arg_syscall_allow_list, settings->syscall_allow_list);
 +                        strv_free_and_replace(arg_syscall_deny_list, settings->syscall_deny_list);
                  }
  
  #if HAVE_SECCOMP
@@@ -5179,8 -5148,7 +5185,8 @@@ static int run(int argc, char *argv[]) 
                          }
  
                          r = verity_metadata_load(arg_image, NULL, arg_root_hash ? NULL : &arg_root_hash, &arg_root_hash_size,
 -                                        arg_verity_data ? NULL : &arg_verity_data);
 +                                        arg_verity_data ? NULL : &arg_verity_data,
 +                                        arg_root_hash_sig_path || arg_root_hash_sig ? NULL : &arg_root_hash_sig_path);
                          if (r < 0) {
                                  log_error_errno(r, "Failed to read verity artefacts for %s: %m", arg_image);
                                  goto finish;
                  if (!arg_root_hash && dissected_image->can_verity)
                          log_notice("Note: image %s contains verity information, but no root hash specified! Proceeding without integrity checking.", arg_image);
  
 -                r = dissected_image_decrypt_interactively(dissected_image, NULL, arg_root_hash, arg_root_hash_size, arg_verity_data, 0, &decrypted_image);
 +                r = dissected_image_decrypt_interactively(dissected_image, NULL, arg_root_hash, arg_root_hash_size, arg_verity_data, arg_root_hash_sig_path, arg_root_hash_sig, arg_root_hash_sig_size, 0, &decrypted_image);
                  if (r < 0)
                          goto finish;
  
diff --combined src/portable/portable.c
index c7c11a48f2419e6b428f3f573d8d1f8bb30feb18,61c1d475b8f4e9982d58eb2516c3499c5343066f..48294d4c492abf9701df8432face2a111469de28
@@@ -701,6 -701,7 +701,7 @@@ static int install_chroot_dropin
                                 "[Service]\n",
                                 IN_SET(type, IMAGE_DIRECTORY, IMAGE_SUBVOLUME) ? "RootDirectory=" : "RootImage=", image_path, "\n"
                                 "Environment=PORTABLE=", basename(image_path), "\n"
+                                "BindReadOnlyPaths=-/etc/os-release:/run/host/etc/os-release /usr/lib/os-release:/run/host/usr/lib/os-release\n"
                                 "LogExtraFields=PORTABLE=", basename(image_path), "\n",
                                 NULL))
  
@@@ -877,7 -878,7 +878,7 @@@ static int attach_unit_file
                  _cleanup_(unlink_and_freep) char *tmp = NULL;
                  _cleanup_close_ int fd = -1;
  
 -                fd = open_tmpfile_linkable(where, O_WRONLY|O_CLOEXEC, &tmp);
 +                fd = open_tmpfile_linkable(path, O_WRONLY|O_CLOEXEC, &tmp);
                  if (fd < 0)
                          return log_debug_errno(fd, "Failed to create unit file '%s': %m", path);
  
@@@ -1125,7 -1126,7 +1126,7 @@@ int portable_detach
                  sd_bus_error *error) {
  
          _cleanup_(lookup_paths_free) LookupPaths paths = {};
 -        _cleanup_set_free_free_ Set *unit_files = NULL, *markers = NULL;
 +        _cleanup_set_free_ Set *unit_files = NULL, *markers = NULL;
          _cleanup_closedir_ DIR *d = NULL;
          const char *where, *item;
          Iterator iterator;
                  return log_debug_errno(errno, "Failed to open '%s' directory: %m", where);
          }
  
 -        markers = set_new(&path_hash_ops);
 -        if (!markers)
 -                return -ENOMEM;
 -
          FOREACH_DIRENT(de, d, return log_debug_errno(errno, "Failed to enumerate '%s' directory: %m", where)) {
                  _cleanup_free_ char *marker = NULL;
                  UnitFileState state;
                  if (path_is_absolute(marker) &&
                      !image_in_search_path(IMAGE_PORTABLE, marker)) {
  
 -                        r = set_ensure_allocated(&markers, &path_hash_ops);
 +                        r = set_ensure_consume(&markers, &path_hash_ops_free, TAKE_PTR(marker));
                          if (r < 0)
                                  return r;
 -
 -                        r = set_put(markers, marker);
 -                        if (r >= 0)
 -                                marker = NULL;
 -                        else if (r != -EEXIST)
 -                                return r;
                  }
          }