From ecc4287dee2d81570240625092813154ca770dea Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 27 May 2024 13:30:31 +0200 Subject: [PATCH] vmspawn: by default, let machined register a cgroup for VMs This mimics what we do in nspawn: if registration is enabled we'll let machined allocate a scope unit for us. When --keep-unit is used we'll register without creating a new scope. This brings behaviour more inline with what nspawn does, exposing the same sets of options. --- src/vmspawn/vmspawn-register.c | 6 ++++-- src/vmspawn/vmspawn-register.h | 4 +++- src/vmspawn/vmspawn.c | 17 ++++++++++++++++- test/units/TEST-50-DISSECT.mountfsd.sh | 2 +- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/vmspawn/vmspawn-register.c b/src/vmspawn/vmspawn-register.c index 2130fd9108b..124ee111b2d 100644 --- a/src/vmspawn/vmspawn-register.c +++ b/src/vmspawn/vmspawn-register.c @@ -22,7 +22,8 @@ int register_machine( const char *directory, unsigned cid, const char *address, - const char *key_path) { + const char *key_path, + bool keep_unit) { _cleanup_(varlink_unrefp) Varlink *vl = NULL; int r; @@ -71,7 +72,8 @@ int register_machine( SD_JSON_BUILD_PAIR_CONDITION(!!directory, "rootDirectory", SD_JSON_BUILD_STRING(directory)), SD_JSON_BUILD_PAIR_CONDITION(!!address, "sshAddress", SD_JSON_BUILD_STRING(address)), SD_JSON_BUILD_PAIR_CONDITION(!!key_path, "sshPrivateKeyPath", SD_JSON_BUILD_STRING(key_path)), - SD_JSON_BUILD_PAIR_CONDITION(isatty(STDIN_FILENO), "allowInteractiveAuthentication", SD_JSON_BUILD_BOOLEAN(true))); + SD_JSON_BUILD_PAIR_CONDITION(isatty(STDIN_FILENO), "allowInteractiveAuthentication", SD_JSON_BUILD_BOOLEAN(true)), + SD_JSON_BUILD_PAIR_CONDITION(!keep_unit, "allocateUnit", SD_JSON_BUILD_BOOLEAN(true))); } int unregister_machine(sd_bus *bus, const char *machine_name) { diff --git a/src/vmspawn/vmspawn-register.h b/src/vmspawn/vmspawn-register.h index 69f56714b2b..d46e28c7925 100644 --- a/src/vmspawn/vmspawn-register.h +++ b/src/vmspawn/vmspawn-register.h @@ -11,5 +11,7 @@ int register_machine( const char *directory, unsigned cid, const char *address, - const char *key_path); + const char *key_path, + bool keep_unit); + int unregister_machine(sd_bus *bus, const char *machine_name); diff --git a/src/vmspawn/vmspawn.c b/src/vmspawn/vmspawn.c index 971844e10c7..05eb443bd08 100644 --- a/src/vmspawn/vmspawn.c +++ b/src/vmspawn/vmspawn.c @@ -107,6 +107,7 @@ static char *arg_forward_journal = NULL; static bool arg_runtime_directory_created = false; static bool arg_privileged = false; static bool arg_register = false; +static bool arg_keep_unit = false; static sd_id128_t arg_uuid = {}; static char **arg_kernel_cmdline_extra = NULL; static char **arg_extra_drives = NULL; @@ -170,6 +171,7 @@ static int help(void) { " --uuid=UUID Set a specific machine UUID for the VM\n" "\n%3$sProperties:%4$s\n" " --register=BOOLEAN Register VM with systemd-machined\n" + " --keep-unit Don't let systemd-machined allocate scope unit for us\n" "\n%3$sUser Namespacing:%4$s\n" " --private-users=UIDBASE[:NUIDS]\n" " Configure the UID/GID range to map into the\n" @@ -235,6 +237,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_NETWORK_USER_MODE, ARG_UUID, ARG_REGISTER, + ARG_KEEP_UNIT, ARG_BIND, ARG_BIND_RO, ARG_EXTRA_DRIVE, @@ -277,6 +280,7 @@ static int parse_argv(int argc, char *argv[]) { { "network-user-mode", no_argument, NULL, ARG_NETWORK_USER_MODE }, { "uuid", required_argument, NULL, ARG_UUID }, { "register", required_argument, NULL, ARG_REGISTER }, + { "keep-unit", no_argument, NULL, ARG_KEEP_UNIT }, { "bind", required_argument, NULL, ARG_BIND }, { "bind-ro", required_argument, NULL, ARG_BIND_RO }, { "extra-drive", required_argument, NULL, ARG_EXTRA_DRIVE }, @@ -443,6 +447,11 @@ static int parse_argv(int argc, char *argv[]) { r = parse_boolean_argument("--register=", optarg, &arg_register); if (r < 0) return r; + + break; + + case ARG_KEEP_UNIT: + arg_keep_unit = true; break; case ARG_BIND: @@ -2055,7 +2064,8 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) { arg_directory, child_cid, child_cid != VMADDR_CID_ANY ? vm_address : NULL, - ssh_private_key_path); + ssh_private_key_path, + arg_keep_unit); if (r < 0) return r; } @@ -2229,6 +2239,11 @@ static int verify_arguments(void) { if (!strv_isempty(arg_initrds) && !arg_linux) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Option --initrd= cannot be used without --linux=."); + if (arg_keep_unit && arg_register && cg_pid_get_owner_uid(0, NULL) >= 0) + /* Save the user from accidentally registering either user-$SESSION.scope or user@.service. + * The latter is not technically a user session, but we don't need to labour the point. */ + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--keep-unit --register=yes may not be used when invoked from a user session."); + return 0; } diff --git a/test/units/TEST-50-DISSECT.mountfsd.sh b/test/units/TEST-50-DISSECT.mountfsd.sh index 604a9dbf387..0ab1a610796 100755 --- a/test/units/TEST-50-DISSECT.mountfsd.sh +++ b/test/units/TEST-50-DISSECT.mountfsd.sh @@ -84,7 +84,7 @@ if ! systemd-detect-virt -c; then -p DelegateSubgroup=supervisor \ -p Environment=SYSTEMD_LOG_LEVEL=debug \ --wait -- \ - systemd-nspawn --keep-unit -i /var/tmp/unpriv.raw --read-only --pipe echo thisisatest >/tmp/unpriv.out2 + systemd-nspawn --keep-unit --register=no -i /var/tmp/unpriv.raw --read-only --pipe echo thisisatest >/tmp/unpriv.out2 echo thisisatest | cmp /tmp/unpriv.out2 - fi