mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 08:25:20 +09:00
machined: introduce per-user instance (#39123)
This is the first part of #38728, just the machined stuff, no the importd stuff. This definitely makes sense of its own, hence let's get this in first. The original PR contains a tescase that tests machined + importd in combination. This PR here hence is without a testcase, but it's there, just in the other PR. This looks large and is large, but do note that much of the machined changes are very repetitive: they conditionalize PK checks to the system version, as PK doesn't make sense in the use rversion.
This commit is contained in:
@@ -15,3 +15,20 @@ const char* runtime_scope_to_string(RuntimeScope scope) _const_;
|
||||
RuntimeScope runtime_scope_from_string(const char *s) _const_;
|
||||
|
||||
const char* runtime_scope_cmdline_option_to_string(RuntimeScope scope) _const_;
|
||||
|
||||
static inline mode_t runtime_scope_to_socket_mode(RuntimeScope scope) {
|
||||
/* Returns the right socket mode to use for binding AF_UNIX sockets intended for the specified
|
||||
* scope. If system mode is selected the whole system can connect to it, if user mode is selected
|
||||
* only the user can connect to it. */
|
||||
|
||||
switch (scope) {
|
||||
case RUNTIME_SCOPE_SYSTEM:
|
||||
return 0666;
|
||||
|
||||
case RUNTIME_SCOPE_USER:
|
||||
return 0600;
|
||||
|
||||
default:
|
||||
return MODE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ static int run(int argc, char *argv[]) {
|
||||
"A service to create, remove, change or inspect home areas.",
|
||||
BUS_IMPLEMENTATIONS(&manager_object,
|
||||
&log_control_object),
|
||||
/* runtime_scope= */ NULL,
|
||||
argc, argv);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
@@ -1988,6 +1988,7 @@ static int run(int argc, char *argv[]) {
|
||||
"Manage the system hostname and related metadata.",
|
||||
BUS_IMPLEMENTATIONS(&manager_object,
|
||||
&log_control_object),
|
||||
/* runtime_scope= */ NULL,
|
||||
argc, argv);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
@@ -2019,6 +2019,7 @@ static int run(int argc, char *argv[]) {
|
||||
"VM and container image import and export service.",
|
||||
BUS_IMPLEMENTATIONS(&manager_object,
|
||||
&log_control_object),
|
||||
/* runtime_scope= */ NULL,
|
||||
argc, argv);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
@@ -33,32 +33,54 @@ int user_search_dirs(const char *suffix, char ***ret_config_dirs, char ***ret_da
|
||||
return 0;
|
||||
}
|
||||
|
||||
int runtime_directory(RuntimeScope scope, const char *suffix, char **ret) {
|
||||
int runtime_directory_generic(RuntimeScope scope, const char *suffix, char **ret) {
|
||||
int r;
|
||||
|
||||
assert(IN_SET(scope, RUNTIME_SCOPE_SYSTEM, RUNTIME_SCOPE_USER));
|
||||
assert(suffix);
|
||||
assert(ret);
|
||||
|
||||
/* Accept $RUNTIME_DIRECTORY as authoritative
|
||||
/* This does not bother with $RUNTIME_DIRECTORY, and hence can be applied to get other service's
|
||||
* runtime dir */
|
||||
|
||||
switch (scope) {
|
||||
case RUNTIME_SCOPE_USER:
|
||||
r = xdg_user_runtime_dir(suffix, ret);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
|
||||
case RUNTIME_SCOPE_SYSTEM: {
|
||||
char *d = path_join("/run", suffix);
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
*ret = d;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int runtime_directory(RuntimeScope scope, const char *fallback_suffix, char **ret) {
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
/* Accept $RUNTIME_DIRECTORY as authoritative, i.e. only works for our service's own runtime dir.
|
||||
*
|
||||
* If it's missing, apply the suffix to /run/, or $XDG_RUNTIME_DIR if we are in a user runtime scope.
|
||||
*
|
||||
* Return value indicates whether the suffix was applied or not */
|
||||
* Return value indicates whether the suffix was applied or not. */
|
||||
|
||||
const char *e = secure_getenv("RUNTIME_DIRECTORY");
|
||||
if (e)
|
||||
return strdup_to(ret, e);
|
||||
|
||||
if (scope == RUNTIME_SCOPE_USER) {
|
||||
r = xdg_user_runtime_dir(suffix, ret);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else {
|
||||
char *d = path_join("/run", suffix);
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
*ret = d;
|
||||
}
|
||||
r = runtime_directory_generic(scope, fallback_suffix, ret);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,8 @@ int lookup_paths_init_or_warn(LookupPaths *lp, RuntimeScope scope, LookupPathsFl
|
||||
void lookup_paths_log(LookupPaths *p);
|
||||
void lookup_paths_done(LookupPaths *p);
|
||||
|
||||
int runtime_directory(RuntimeScope scope, const char *suffix, char **ret);
|
||||
int runtime_directory_generic(RuntimeScope scope, const char *suffix, char **ret);
|
||||
int runtime_directory(RuntimeScope scope, const char *fallback_suffix, char **ret);
|
||||
|
||||
/* We don't treat /etc/xdg/systemd/ in these functions as the xdg base dir spec suggests because we assume
|
||||
* that is a link to /etc/systemd/ anyway. */
|
||||
|
||||
@@ -635,6 +635,7 @@ static int run(int argc, char *argv[]) {
|
||||
"Manage system locale settings and key mappings.",
|
||||
BUS_IMPLEMENTATIONS(&manager_object,
|
||||
&log_control_object),
|
||||
/* runtime_scope= */ NULL,
|
||||
argc, argv);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
@@ -1340,6 +1340,7 @@ static int run(int argc, char *argv[]) {
|
||||
"Manager for user logins and devices and privileged operations.",
|
||||
BUS_IMPLEMENTATIONS(&manager_object,
|
||||
&log_control_object),
|
||||
/* runtime_scope= */ NULL,
|
||||
argc, argv);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
@@ -40,22 +40,24 @@ int bus_image_method_remove(
|
||||
if (m->n_operations >= OPERATIONS_MAX)
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing operations.");
|
||||
|
||||
const char *details[] = {
|
||||
"image", image->name,
|
||||
"verb", "remove",
|
||||
NULL
|
||||
};
|
||||
if (m->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
const char *details[] = {
|
||||
"image", image->name,
|
||||
"verb", "remove",
|
||||
NULL
|
||||
};
|
||||
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
"org.freedesktop.machine1.manage-images",
|
||||
details,
|
||||
&m->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
"org.freedesktop.machine1.manage-images",
|
||||
details,
|
||||
&m->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
}
|
||||
|
||||
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
|
||||
return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
|
||||
@@ -65,7 +67,7 @@ int bus_image_method_remove(
|
||||
return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
|
||||
if (r == 0) {
|
||||
errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
|
||||
r = image_remove(image);
|
||||
r = image_remove(image, m->runtime_scope);
|
||||
report_errno_and_exit(errno_pipe_fd[1], r);
|
||||
}
|
||||
|
||||
@@ -101,23 +103,25 @@ int bus_image_method_rename(
|
||||
if (!image_name_is_valid(new_name))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", new_name);
|
||||
|
||||
const char *details[] = {
|
||||
"image", image->name,
|
||||
"verb", "rename",
|
||||
"new_name", new_name,
|
||||
NULL
|
||||
};
|
||||
if (m->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
const char *details[] = {
|
||||
"image", image->name,
|
||||
"verb", "rename",
|
||||
"new_name", new_name,
|
||||
NULL
|
||||
};
|
||||
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
"org.freedesktop.machine1.manage-images",
|
||||
details,
|
||||
&m->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
"org.freedesktop.machine1.manage-images",
|
||||
details,
|
||||
&m->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
}
|
||||
|
||||
r = rename_image_and_update_cache(m, image, new_name);
|
||||
if (r < 0)
|
||||
@@ -150,23 +154,25 @@ int bus_image_method_clone(
|
||||
if (!image_name_is_valid(new_name))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", new_name);
|
||||
|
||||
const char *details[] = {
|
||||
"image", image->name,
|
||||
"verb", "clone",
|
||||
"new_name", new_name,
|
||||
NULL
|
||||
};
|
||||
if (m->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
const char *details[] = {
|
||||
"image", image->name,
|
||||
"verb", "clone",
|
||||
"new_name", new_name,
|
||||
NULL
|
||||
};
|
||||
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
"org.freedesktop.machine1.manage-images",
|
||||
details,
|
||||
&m->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
"org.freedesktop.machine1.manage-images",
|
||||
details,
|
||||
&m->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
}
|
||||
|
||||
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
|
||||
return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
|
||||
@@ -199,7 +205,7 @@ int bus_image_method_mark_read_only(
|
||||
sd_bus_error *error) {
|
||||
|
||||
Image *image = userdata;
|
||||
Manager *m = image->userdata;
|
||||
Manager *m = ASSERT_PTR(image->userdata);
|
||||
int read_only, r;
|
||||
|
||||
assert(message);
|
||||
@@ -208,25 +214,27 @@ int bus_image_method_mark_read_only(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
const char *details[] = {
|
||||
"image", image->name,
|
||||
"verb", "mark_read_only",
|
||||
"read_only", one_zero(read_only),
|
||||
NULL
|
||||
};
|
||||
if (m->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
const char *details[] = {
|
||||
"image", image->name,
|
||||
"verb", "mark_read_only",
|
||||
"read_only", one_zero(read_only),
|
||||
NULL
|
||||
};
|
||||
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
"org.freedesktop.machine1.manage-images",
|
||||
details,
|
||||
&m->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
"org.freedesktop.machine1.manage-images",
|
||||
details,
|
||||
&m->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
}
|
||||
|
||||
r = image_read_only(image, read_only);
|
||||
r = image_read_only(image, read_only, m->runtime_scope);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -251,22 +259,24 @@ int bus_image_method_set_limit(
|
||||
if (!FILE_SIZE_VALID_OR_INFINITY(limit))
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range");
|
||||
|
||||
const char *details[] = {
|
||||
"machine", image->name,
|
||||
"verb", "set_limit",
|
||||
NULL
|
||||
};
|
||||
if (m->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
const char *details[] = {
|
||||
"machine", image->name,
|
||||
"verb", "set_limit",
|
||||
NULL
|
||||
};
|
||||
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
"org.freedesktop.machine1.manage-images",
|
||||
details,
|
||||
&m->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
"org.freedesktop.machine1.manage-images",
|
||||
details,
|
||||
&m->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
}
|
||||
|
||||
r = image_set_limit(image, limit);
|
||||
if (r < 0)
|
||||
@@ -280,11 +290,12 @@ int bus_image_method_get_hostname(
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
Image *image = userdata;
|
||||
Image *image = ASSERT_PTR(userdata);
|
||||
Manager *m = ASSERT_PTR(image->userdata);
|
||||
int r;
|
||||
|
||||
if (!image->metadata_valid) {
|
||||
r = image_read_metadata(image, &image_policy_container);
|
||||
r = image_read_metadata(image, &image_policy_container, m->runtime_scope);
|
||||
if (r < 0)
|
||||
return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m");
|
||||
}
|
||||
@@ -298,11 +309,12 @@ int bus_image_method_get_machine_id(
|
||||
sd_bus_error *error) {
|
||||
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||
Image *image = userdata;
|
||||
Image *image = ASSERT_PTR(userdata);
|
||||
Manager *m = ASSERT_PTR(image->userdata);
|
||||
int r;
|
||||
|
||||
if (!image->metadata_valid) {
|
||||
r = image_read_metadata(image, &image_policy_container);
|
||||
r = image_read_metadata(image, &image_policy_container, m->runtime_scope);
|
||||
if (r < 0)
|
||||
return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m");
|
||||
}
|
||||
@@ -326,11 +338,12 @@ int bus_image_method_get_machine_info(
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
Image *image = userdata;
|
||||
Image *image = ASSERT_PTR(userdata);
|
||||
Manager *m = ASSERT_PTR(image->userdata);
|
||||
int r;
|
||||
|
||||
if (!image->metadata_valid) {
|
||||
r = image_read_metadata(image, &image_policy_container);
|
||||
r = image_read_metadata(image, &image_policy_container, m->runtime_scope);
|
||||
if (r < 0)
|
||||
return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m");
|
||||
}
|
||||
@@ -343,11 +356,12 @@ int bus_image_method_get_os_release(
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
Image *image = userdata;
|
||||
Image *image = ASSERT_PTR(userdata);
|
||||
Manager *m = ASSERT_PTR(image->userdata);
|
||||
int r;
|
||||
|
||||
if (!image->metadata_valid) {
|
||||
r = image_read_metadata(image, &image_policy_container);
|
||||
r = image_read_metadata(image, &image_policy_container, m->runtime_scope);
|
||||
if (r < 0)
|
||||
return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m");
|
||||
}
|
||||
|
||||
@@ -66,15 +66,17 @@ int vl_method_update_image(sd_varlink *link, sd_json_variant *parameters, sd_var
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = varlink_verify_polkit_async(
|
||||
link,
|
||||
manager->bus,
|
||||
"org.freedesktop.machine1.manage-images",
|
||||
(const char**) STRV_MAKE("image", image->name,
|
||||
"verb", "update"),
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
r = varlink_verify_polkit_async(
|
||||
link,
|
||||
manager->system_bus,
|
||||
"org.freedesktop.machine1.manage-images",
|
||||
(const char**) STRV_MAKE("image", image->name,
|
||||
"verb", "update"),
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (p.new_name) {
|
||||
r = rename_image_and_update_cache(manager, image, p.new_name);
|
||||
@@ -83,7 +85,7 @@ int vl_method_update_image(sd_varlink *link, sd_json_variant *parameters, sd_var
|
||||
}
|
||||
|
||||
if (p.read_only >= 0) {
|
||||
r = image_read_only(image, p.read_only);
|
||||
r = image_read_only(image, p.read_only, manager->runtime_scope);
|
||||
if (r < 0)
|
||||
RET_GATHER(ret, log_debug_errno(r, "Failed to toggle image read only, ignoring: %m"));
|
||||
}
|
||||
@@ -139,16 +141,18 @@ int vl_method_clone_image(sd_varlink *link, sd_json_variant *parameters, sd_varl
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = varlink_verify_polkit_async(
|
||||
link,
|
||||
manager->bus,
|
||||
"org.freedesktop.machine1.manage-images",
|
||||
(const char**) STRV_MAKE("image", image->name,
|
||||
"verb", "clone",
|
||||
"new_name", p.new_name),
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
r = varlink_verify_polkit_async(
|
||||
link,
|
||||
manager->system_bus,
|
||||
"org.freedesktop.machine1.manage-images",
|
||||
(const char**) STRV_MAKE("image", image->name,
|
||||
"verb", "clone",
|
||||
"new_name", p.new_name),
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
|
||||
return log_debug_errno(errno, "Failed to open pipe: %m");
|
||||
@@ -207,15 +211,17 @@ int vl_method_remove_image(sd_varlink *link, sd_json_variant *parameters, sd_var
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = varlink_verify_polkit_async(
|
||||
link,
|
||||
manager->bus,
|
||||
"org.freedesktop.machine1.manage-images",
|
||||
(const char**) STRV_MAKE("image", image->name,
|
||||
"verb", "remove"),
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
r = varlink_verify_polkit_async(
|
||||
link,
|
||||
manager->system_bus,
|
||||
"org.freedesktop.machine1.manage-images",
|
||||
(const char**) STRV_MAKE("image", image->name,
|
||||
"verb", "remove"),
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
|
||||
return log_debug_errno(errno, "Failed to open pipe: %m");
|
||||
@@ -225,7 +231,7 @@ int vl_method_remove_image(sd_varlink *link, sd_json_variant *parameters, sd_var
|
||||
return log_debug_errno(r, "Failed to fork: %m");
|
||||
if (r == 0) {
|
||||
errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
|
||||
r = image_remove(image);
|
||||
r = image_remove(image, manager->runtime_scope);
|
||||
report_errno_and_exit(errno_pipe_fd[1], r);
|
||||
}
|
||||
|
||||
@@ -262,21 +268,23 @@ int vl_method_set_pool_limit(sd_varlink *link, sd_json_variant *parameters, sd_v
|
||||
if (!FILE_SIZE_VALID_OR_INFINITY(limit))
|
||||
return sd_varlink_error_invalid_parameter_name(link, "limit");
|
||||
|
||||
r = varlink_verify_polkit_async(
|
||||
link,
|
||||
manager->bus,
|
||||
"org.freedesktop.machine1.manage-images",
|
||||
(const char**) STRV_MAKE("verb", "set_pool_limit"),
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
r = varlink_verify_polkit_async(
|
||||
link,
|
||||
manager->system_bus,
|
||||
"org.freedesktop.machine1.manage-images",
|
||||
(const char**) STRV_MAKE("verb", "set_pool_limit"),
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Set up the machine directory if necessary */
|
||||
r = setup_machine_directory(/* error = */ NULL, /* use_btrfs_subvol= */ true, /* use_btrfs_quota= */ true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = image_set_pool_limit(IMAGE_MACHINE, limit);
|
||||
r = image_set_pool_limit(manager->runtime_scope, IMAGE_MACHINE, limit);
|
||||
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
|
||||
return sd_varlink_error(link, VARLINK_ERROR_MACHINE_IMAGE_NOT_SUPPORTED, NULL);
|
||||
if (r < 0)
|
||||
@@ -394,15 +402,17 @@ int vl_method_clean_pool(sd_varlink *link, sd_json_variant *parameters, sd_varli
|
||||
if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
|
||||
return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL);
|
||||
|
||||
r = varlink_verify_polkit_async(
|
||||
link,
|
||||
manager->bus,
|
||||
"org.freedesktop.machine1.manage-images",
|
||||
(const char**) STRV_MAKE("mode", image_clean_pool_mode_to_string(mode),
|
||||
"verb", "clean_pool"),
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
r = varlink_verify_polkit_async(
|
||||
link,
|
||||
manager->system_bus,
|
||||
"org.freedesktop.machine1.manage-images",
|
||||
(const char**) STRV_MAKE("mode", image_clean_pool_mode_to_string(mode),
|
||||
"verb", "clean_pool"),
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
Operation *op;
|
||||
r = image_clean_pool_operation(manager, mode, &op);
|
||||
|
||||
@@ -143,7 +143,7 @@ int image_clean_pool_operation(Manager *manager, ImageCleanPoolMode mode, Operat
|
||||
if (mode == IMAGE_CLEAN_POOL_REMOVE_HIDDEN && !image_is_hidden(image))
|
||||
continue;
|
||||
|
||||
r = image_remove(image);
|
||||
r = image_remove(image, manager->runtime_scope);
|
||||
if (r == -EBUSY) {
|
||||
log_debug("Keeping image '%s' because it's currently used.", image->name);
|
||||
continue;
|
||||
|
||||
@@ -55,24 +55,26 @@ int bus_machine_method_unregister(sd_bus_message *message, void *userdata, sd_bu
|
||||
|
||||
assert(message);
|
||||
|
||||
const char *details[] = {
|
||||
"machine", m->name,
|
||||
"verb", "unregister",
|
||||
NULL
|
||||
};
|
||||
if (m->manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
const char *details[] = {
|
||||
"machine", m->name,
|
||||
"verb", "unregister",
|
||||
NULL
|
||||
};
|
||||
|
||||
r = bus_verify_polkit_async_full(
|
||||
message,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
details,
|
||||
m->uid,
|
||||
/* flags= */ 0,
|
||||
&m->manager->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
r = bus_verify_polkit_async_full(
|
||||
message,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
details,
|
||||
m->uid,
|
||||
/* flags= */ 0,
|
||||
&m->manager->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
}
|
||||
|
||||
r = machine_finalize(m);
|
||||
if (r < 0)
|
||||
@@ -87,24 +89,26 @@ int bus_machine_method_terminate(sd_bus_message *message, void *userdata, sd_bus
|
||||
|
||||
assert(message);
|
||||
|
||||
const char *details[] = {
|
||||
"machine", m->name,
|
||||
"verb", "terminate",
|
||||
NULL
|
||||
};
|
||||
if (m->manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
const char *details[] = {
|
||||
"machine", m->name,
|
||||
"verb", "terminate",
|
||||
NULL
|
||||
};
|
||||
|
||||
r = bus_verify_polkit_async_full(
|
||||
message,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
details,
|
||||
m->uid,
|
||||
/* flags= */ 0,
|
||||
&m->manager->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
r = bus_verify_polkit_async_full(
|
||||
message,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
details,
|
||||
m->uid,
|
||||
/* flags= */ 0,
|
||||
&m->manager->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
}
|
||||
|
||||
r = machine_stop(m);
|
||||
if (r < 0)
|
||||
@@ -137,24 +141,26 @@ int bus_machine_method_kill(sd_bus_message *message, void *userdata, sd_bus_erro
|
||||
if (!SIGNAL_VALID(signo))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
|
||||
|
||||
const char *details[] = {
|
||||
"machine", m->name,
|
||||
"verb", "kill",
|
||||
NULL
|
||||
};
|
||||
if (m->manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
const char *details[] = {
|
||||
"machine", m->name,
|
||||
"verb", "kill",
|
||||
NULL
|
||||
};
|
||||
|
||||
r = bus_verify_polkit_async_full(
|
||||
message,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
details,
|
||||
m->uid,
|
||||
/* flags= */ 0,
|
||||
&m->manager->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
r = bus_verify_polkit_async_full(
|
||||
message,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
details,
|
||||
m->uid,
|
||||
/* flags= */ 0,
|
||||
&m->manager->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
}
|
||||
|
||||
r = machine_kill(m, whom, signo);
|
||||
if (r < 0)
|
||||
@@ -260,23 +266,25 @@ int bus_machine_method_open_pty(sd_bus_message *message, void *userdata, sd_bus_
|
||||
|
||||
assert(message);
|
||||
|
||||
const char *details[] = {
|
||||
"machine", m->name,
|
||||
NULL
|
||||
};
|
||||
if (m->manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
const char *details[] = {
|
||||
"machine", m->name,
|
||||
NULL
|
||||
};
|
||||
|
||||
r = bus_verify_polkit_async_full(
|
||||
message,
|
||||
m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-open-pty" : "org.freedesktop.machine1.open-pty",
|
||||
details,
|
||||
m->uid,
|
||||
/* flags= */ 0,
|
||||
&m->manager->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
r = bus_verify_polkit_async_full(
|
||||
message,
|
||||
m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-open-pty" : "org.freedesktop.machine1.open-pty",
|
||||
details,
|
||||
m->uid,
|
||||
/* flags= */ 0,
|
||||
&m->manager->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
}
|
||||
|
||||
master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC, &pty_name);
|
||||
if (master < 0)
|
||||
@@ -302,24 +310,26 @@ int bus_machine_method_open_login(sd_bus_message *message, void *userdata, sd_bu
|
||||
|
||||
assert(message);
|
||||
|
||||
const char *details[] = {
|
||||
"machine", m->name,
|
||||
"verb", "login",
|
||||
NULL
|
||||
};
|
||||
if (m->manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
const char *details[] = {
|
||||
"machine", m->name,
|
||||
"verb", "login",
|
||||
NULL
|
||||
};
|
||||
|
||||
r = bus_verify_polkit_async_full(
|
||||
message,
|
||||
m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-login" : "org.freedesktop.machine1.login",
|
||||
details,
|
||||
m->uid,
|
||||
/* flags= */ 0,
|
||||
&m->manager->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
r = bus_verify_polkit_async_full(
|
||||
message,
|
||||
m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-login" : "org.freedesktop.machine1.login",
|
||||
details,
|
||||
m->uid,
|
||||
/* flags= */ 0,
|
||||
&m->manager->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
}
|
||||
|
||||
master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC, &pty_name);
|
||||
if (master < 0)
|
||||
@@ -345,7 +355,6 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
|
||||
_cleanup_free_ char *pty_name = NULL;
|
||||
_cleanup_close_ int master = -EBADF;
|
||||
_cleanup_strv_free_ char **env = NULL, **args_wire = NULL, **args = NULL;
|
||||
_cleanup_free_ char *command_line = NULL;
|
||||
Machine *m = ASSERT_PTR(userdata);
|
||||
const char *user, *path;
|
||||
int r;
|
||||
@@ -402,29 +411,32 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
|
||||
if (!strv_env_is_valid(env))
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
|
||||
|
||||
command_line = strv_join(args, " ");
|
||||
if (!command_line)
|
||||
return -ENOMEM;
|
||||
const char *details[] = {
|
||||
"machine", m->name,
|
||||
"user", user,
|
||||
"program", path,
|
||||
"command_line", command_line,
|
||||
NULL
|
||||
};
|
||||
if (m->manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
_cleanup_free_ char *command_line = strv_join(args, " ");
|
||||
if (!command_line)
|
||||
return -ENOMEM;
|
||||
|
||||
r = bus_verify_polkit_async_full(
|
||||
message,
|
||||
m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-shell" : "org.freedesktop.machine1.shell",
|
||||
details,
|
||||
m->uid,
|
||||
/* flags= */ 0,
|
||||
&m->manager->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
const char *details[] = {
|
||||
"machine", m->name,
|
||||
"user", user,
|
||||
"program", path,
|
||||
"command_line", command_line,
|
||||
NULL
|
||||
};
|
||||
|
||||
r = bus_verify_polkit_async_full(
|
||||
message,
|
||||
m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-shell" : "org.freedesktop.machine1.shell",
|
||||
details,
|
||||
m->uid,
|
||||
/* flags= */ 0,
|
||||
&m->manager->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
}
|
||||
|
||||
master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC, &pty_name);
|
||||
if (master < 0)
|
||||
@@ -470,25 +482,27 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu
|
||||
else if (!path_is_absolute(dest) || !path_is_normalized(dest))
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute and normalized.");
|
||||
|
||||
const char *details[] = {
|
||||
"machine", m->name,
|
||||
"verb", "bind",
|
||||
"src", src,
|
||||
"dest", dest,
|
||||
NULL
|
||||
};
|
||||
if (m->manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
const char *details[] = {
|
||||
"machine", m->name,
|
||||
"verb", "bind",
|
||||
"src", src,
|
||||
"dest", dest,
|
||||
NULL
|
||||
};
|
||||
|
||||
/* NB: For now not opened up to owner of machine without auth */
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
details,
|
||||
&m->manager->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
/* NB: For now not opened up to owner of machine without auth */
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
details,
|
||||
&m->manager->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
}
|
||||
|
||||
r = machine_get_uid_shift(m, &uid);
|
||||
if (r < 0)
|
||||
@@ -556,25 +570,27 @@ int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_erro
|
||||
else if (!path_is_absolute(dest))
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute.");
|
||||
|
||||
const char *details[] = {
|
||||
"machine", m->name,
|
||||
"verb", "copy",
|
||||
"src", src,
|
||||
"dest", dest,
|
||||
NULL
|
||||
};
|
||||
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
const char *details[] = {
|
||||
"machine", m->name,
|
||||
"verb", "copy",
|
||||
"src", src,
|
||||
"dest", dest,
|
||||
NULL
|
||||
};
|
||||
|
||||
/* NB: For now not opened up to owner of machine without auth */
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
details,
|
||||
&manager->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
/* NB: For now not opened up to owner of machine without auth */
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
details,
|
||||
&manager->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
}
|
||||
|
||||
copy_from = strstr(sd_bus_message_get_member(message), "CopyFrom");
|
||||
|
||||
@@ -602,23 +618,25 @@ int bus_machine_method_open_root_directory(sd_bus_message *message, void *userda
|
||||
|
||||
assert(message);
|
||||
|
||||
const char *details[] = {
|
||||
"machine", m->name,
|
||||
"verb", "open_root_directory",
|
||||
NULL
|
||||
};
|
||||
if (m->manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
const char *details[] = {
|
||||
"machine", m->name,
|
||||
"verb", "open_root_directory",
|
||||
NULL
|
||||
};
|
||||
|
||||
/* NB: For now not opened up to owner of machine without auth */
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
details,
|
||||
&m->manager->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
/* NB: For now not opened up to owner of machine without auth */
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
details,
|
||||
&m->manager->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
}
|
||||
|
||||
fd = machine_open_root_directory(m);
|
||||
if (ERRNO_IS_NEG_NOT_SUPPORTED(fd))
|
||||
@@ -862,7 +880,7 @@ int machine_send_signal(Machine *m, bool new_machine) {
|
||||
return -ENOMEM;
|
||||
|
||||
return sd_bus_emit_signal(
|
||||
m->manager->bus,
|
||||
m->manager->api_bus,
|
||||
"/org/freedesktop/machine1",
|
||||
"org.freedesktop.machine1.Manager",
|
||||
new_machine ? "MachineNew" : "MachineRemoved",
|
||||
|
||||
@@ -155,15 +155,17 @@ int vl_method_register(sd_varlink *link, sd_json_variant *parameters, sd_varlink
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
r = varlink_verify_polkit_async(
|
||||
link,
|
||||
manager->bus,
|
||||
machine->allocate_unit ? "org.freedesktop.machine1.create-machine" : "org.freedesktop.machine1.register-machine",
|
||||
(const char**) STRV_MAKE("name", machine->name,
|
||||
"class", machine_class_to_string(machine->class)),
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
r = varlink_verify_polkit_async(
|
||||
link,
|
||||
manager->system_bus,
|
||||
machine->allocate_unit ? "org.freedesktop.machine1.create-machine" : "org.freedesktop.machine1.register-machine",
|
||||
(const char**) STRV_MAKE("name", machine->name,
|
||||
"class", machine_class_to_string(machine->class)),
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!pidref_is_set(&machine->leader)) {
|
||||
r = varlink_get_peer_pidref(link, &machine->leader);
|
||||
@@ -306,17 +308,19 @@ int vl_method_unregister_internal(sd_varlink *link, sd_json_variant *parameters,
|
||||
Manager *manager = ASSERT_PTR(machine->manager);
|
||||
int r;
|
||||
|
||||
r = varlink_verify_polkit_async_full(
|
||||
link,
|
||||
manager->bus,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
(const char**) STRV_MAKE("name", machine->name,
|
||||
"verb", "unregister"),
|
||||
machine->uid,
|
||||
/* flags= */ 0,
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
r = varlink_verify_polkit_async_full(
|
||||
link,
|
||||
manager->system_bus,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
(const char**) STRV_MAKE("name", machine->name,
|
||||
"verb", "unregister"),
|
||||
machine->uid,
|
||||
/* flags= */ 0,
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = machine_finalize(machine);
|
||||
if (r < 0)
|
||||
@@ -330,17 +334,19 @@ int vl_method_terminate_internal(sd_varlink *link, sd_json_variant *parameters,
|
||||
Manager *manager = ASSERT_PTR(machine->manager);
|
||||
int r;
|
||||
|
||||
r = varlink_verify_polkit_async_full(
|
||||
link,
|
||||
manager->bus,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
(const char**) STRV_MAKE("name", machine->name,
|
||||
"verb", "terminate"),
|
||||
machine->uid,
|
||||
/* flags= */ 0,
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
r = varlink_verify_polkit_async_full(
|
||||
link,
|
||||
manager->system_bus,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
(const char**) STRV_MAKE("name", machine->name,
|
||||
"verb", "terminate"),
|
||||
machine->uid,
|
||||
/* flags= */ 0,
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = machine_stop(machine);
|
||||
if (r < 0)
|
||||
@@ -400,17 +406,19 @@ int vl_method_kill(sd_varlink *link, sd_json_variant *parameters, sd_varlink_met
|
||||
return sd_varlink_error_invalid_parameter_name(link, "whom");
|
||||
}
|
||||
|
||||
r = varlink_verify_polkit_async_full(
|
||||
link,
|
||||
manager->bus,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
(const char**) STRV_MAKE("name", machine->name,
|
||||
"verb", "kill"),
|
||||
machine->uid,
|
||||
/* flags= */ 0,
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
r = varlink_verify_polkit_async_full(
|
||||
link,
|
||||
manager->system_bus,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
(const char**) STRV_MAKE("name", machine->name,
|
||||
"verb", "kill"),
|
||||
machine->uid,
|
||||
/* flags= */ 0,
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = machine_kill(machine, whom, p.signo);
|
||||
if (r < 0)
|
||||
@@ -509,8 +517,8 @@ int vl_method_open(sd_varlink *link, sd_json_variant *parameters, sd_varlink_met
|
||||
};
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
||||
_cleanup_free_ char *ptmx_name = NULL, *command_line = NULL;
|
||||
_cleanup_strv_free_ char **polkit_details = NULL, **args = NULL;
|
||||
const char *user = NULL, *path = NULL; /* gcc complains about uninitialized variables */
|
||||
_cleanup_strv_free_ char **args = NULL;
|
||||
Machine *machine;
|
||||
int r, ptmx_fd_idx;
|
||||
|
||||
@@ -543,17 +551,21 @@ int vl_method_open(sd_varlink *link, sd_json_variant *parameters, sd_varlink_met
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
polkit_details = machine_open_polkit_details(p.mode, machine->name, user, path, command_line);
|
||||
r = varlink_verify_polkit_async_full(
|
||||
link,
|
||||
manager->bus,
|
||||
machine_open_polkit_action(p.mode, machine->class),
|
||||
(const char**) polkit_details,
|
||||
machine->uid,
|
||||
/* flags= */ 0,
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
_cleanup_strv_free_ char **polkit_details = NULL;
|
||||
|
||||
polkit_details = machine_open_polkit_details(p.mode, machine->name, user, path, command_line);
|
||||
r = varlink_verify_polkit_async_full(
|
||||
link,
|
||||
manager->system_bus,
|
||||
machine_open_polkit_action(p.mode, machine->class),
|
||||
(const char**) polkit_details,
|
||||
machine->uid,
|
||||
/* flags= */ 0,
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
ptmx_fd = machine_openpt(machine, O_RDWR|O_NOCTTY|O_CLOEXEC, &ptmx_name);
|
||||
if (ERRNO_IS_NEG_NOT_SUPPORTED(ptmx_fd))
|
||||
@@ -824,18 +836,20 @@ int vl_method_bind_mount(sd_varlink *link, sd_json_variant *parameters, sd_varli
|
||||
if (machine->class != MACHINE_CONTAINER)
|
||||
return sd_varlink_error(link, VARLINK_ERROR_MACHINE_NOT_SUPPORTED, NULL);
|
||||
|
||||
/* NB: For now not opened up to owner of machine without auth */
|
||||
r = varlink_verify_polkit_async(
|
||||
link,
|
||||
manager->bus,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
(const char**) STRV_MAKE("name", machine->name,
|
||||
"verb", "bind",
|
||||
"src", p.src,
|
||||
"dest", dest),
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
/* NB: For now not opened up to owner of machine without auth */
|
||||
r = varlink_verify_polkit_async(
|
||||
link,
|
||||
manager->system_bus,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
(const char**) STRV_MAKE("name", machine->name,
|
||||
"verb", "bind",
|
||||
"src", p.src,
|
||||
"dest", dest),
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = machine_get_uid_shift(machine, &uid_shift);
|
||||
if (r < 0)
|
||||
@@ -936,18 +950,20 @@ int vl_method_copy_internal(sd_varlink *link, sd_json_variant *parameters, sd_va
|
||||
if (machine->class != MACHINE_CONTAINER)
|
||||
return sd_varlink_error(link, VARLINK_ERROR_MACHINE_NOT_SUPPORTED, NULL);
|
||||
|
||||
/* NB: For now not opened up to owner of machine without auth */
|
||||
r = varlink_verify_polkit_async(
|
||||
link,
|
||||
manager->bus,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
(const char**) STRV_MAKE("name", machine->name,
|
||||
"verb", "copy",
|
||||
"src", p.src,
|
||||
"dest", dest),
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
/* NB: For now not opened up to owner of machine without auth */
|
||||
r = varlink_verify_polkit_async(
|
||||
link,
|
||||
manager->system_bus,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
(const char**) STRV_MAKE("name", machine->name,
|
||||
"verb", "copy",
|
||||
"src", p.src,
|
||||
"dest", dest),
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
Operation *op;
|
||||
r = machine_copy_from_to_operation(manager, machine, host_path, container_path, copy_from, copy_flags, &op);
|
||||
@@ -967,15 +983,17 @@ int vl_method_open_root_directory_internal(sd_varlink *link, sd_json_variant *pa
|
||||
int r;
|
||||
|
||||
/* NB: For now not opened up to owner of machine without auth */
|
||||
r = varlink_verify_polkit_async(
|
||||
link,
|
||||
manager->bus,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
(const char**) STRV_MAKE("name", machine->name,
|
||||
"verb", "open_root_directory"),
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
r = varlink_verify_polkit_async(
|
||||
link,
|
||||
manager->system_bus,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
(const char**) STRV_MAKE("name", machine->name,
|
||||
"verb", "open_root_directory"),
|
||||
&manager->polkit_registry);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
fd = machine_open_root_directory(machine);
|
||||
if (ERRNO_IS_NEG_NOT_SUPPORTED(fd))
|
||||
|
||||
@@ -88,7 +88,7 @@ int machine_link(Manager *manager, Machine *machine) {
|
||||
return -EINVAL;
|
||||
|
||||
if (machine->class != MACHINE_HOST) {
|
||||
char *temp = path_join("/run/systemd/machines", machine->name);
|
||||
char *temp = path_join(manager->state_dir, machine->name);
|
||||
if (!temp)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -170,14 +170,14 @@ int machine_save(Machine *m) {
|
||||
|
||||
_cleanup_(unlink_and_freep) char *sl = NULL; /* auto-unlink! */
|
||||
if (m->unit && !m->subgroup) {
|
||||
sl = strjoin("/run/systemd/machines/unit:", m->unit);
|
||||
sl = strjoin(m->manager->state_dir, "/unit:", m->unit);
|
||||
if (!sl)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
r = mkdir_safe_label("/run/systemd/machines", 0755, 0, 0, MKDIR_WARN_MODE);
|
||||
r = mkdir_safe_label(m->manager->state_dir, 0755, 0, 0, MKDIR_WARN_MODE);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create /run/systemd/machines/: %m");
|
||||
return log_error_errno(r, "Failed to create '%s': %m", m->manager->state_dir);
|
||||
|
||||
_cleanup_(unlink_and_freep) char *temp_path = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
@@ -267,7 +267,7 @@ static void machine_unlink(Machine *m) {
|
||||
assert(m);
|
||||
|
||||
if (m->unit && !m->subgroup) {
|
||||
const char *sl = strjoina("/run/systemd/machines/unit:", m->unit);
|
||||
const char *sl = strjoina(m->manager->state_dir, "/unit:", m->unit);
|
||||
(void) unlink(sl);
|
||||
}
|
||||
|
||||
@@ -438,7 +438,7 @@ static int machine_start_scope(
|
||||
return log_oom();
|
||||
|
||||
r = bus_message_new_method_call(
|
||||
machine->manager->bus,
|
||||
machine->manager->api_bus,
|
||||
&m,
|
||||
bus_systemd_mgr,
|
||||
"StartTransientUnit");
|
||||
@@ -920,7 +920,7 @@ int machine_start_getty(Machine *m, const char *ptmx_name, sd_bus_error *error)
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to create DBus to machine: %m");
|
||||
|
||||
container_bus = allocated_bus ?: m->manager->bus;
|
||||
container_bus = allocated_bus ?: m->manager->system_bus;
|
||||
getty = strjoina("container-getty@", p, ".service");
|
||||
|
||||
r = bus_call_method(container_bus, bus_systemd_mgr, "StartUnit", error, /* ret_reply = */ NULL, "ss", getty, "replace");
|
||||
@@ -966,7 +966,7 @@ int machine_start_shell(
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to create DBus to machine: %m");
|
||||
|
||||
container_bus = allocated_bus ?: m->manager->bus;
|
||||
container_bus = allocated_bus ?: m->manager->system_bus;
|
||||
r = bus_message_new_method_call(container_bus, &tm, bus_systemd_mgr, "StartTransientUnit");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -104,6 +104,7 @@ static const char* arg_format = NULL;
|
||||
static const char *arg_uid = NULL;
|
||||
static char **arg_setenv = NULL;
|
||||
static unsigned arg_max_addresses = 1;
|
||||
static RuntimeScope arg_runtime_scope = RUNTIME_SCOPE_SYSTEM;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_setenv, strv_freep);
|
||||
@@ -2099,6 +2100,8 @@ static int help(int argc, char *argv[], void *userdata) {
|
||||
" --no-ask-password Do not ask for system passwords\n"
|
||||
" -H --host=[USER@]HOST Operate on remote host\n"
|
||||
" -M --machine=CONTAINER Operate on local container\n"
|
||||
" --system Connect to system machine manager\n"
|
||||
" --user Connect to user machine manager\n"
|
||||
" -p --property=NAME Show only properties by this name\n"
|
||||
" --value When showing properties, only print the value\n"
|
||||
" -P NAME Equivalent to --value --property=NAME\n"
|
||||
@@ -2152,6 +2155,8 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_FORMAT,
|
||||
ARG_UID,
|
||||
ARG_MAX_ADDRESSES,
|
||||
ARG_SYSTEM,
|
||||
ARG_USER,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
@@ -2181,6 +2186,8 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "uid", required_argument, NULL, ARG_UID },
|
||||
{ "setenv", required_argument, NULL, 'E' },
|
||||
{ "max-addresses", required_argument, NULL, ARG_MAX_ADDRESSES },
|
||||
{ "user", no_argument, NULL, ARG_USER },
|
||||
{ "system", no_argument, NULL, ARG_SYSTEM },
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -2404,6 +2411,14 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
"Invalid number of addresses: %s", optarg);
|
||||
break;
|
||||
|
||||
case ARG_USER:
|
||||
arg_runtime_scope = RUNTIME_SCOPE_USER;
|
||||
break;
|
||||
|
||||
case ARG_SYSTEM:
|
||||
arg_runtime_scope = RUNTIME_SCOPE_SYSTEM;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
@@ -2488,9 +2503,9 @@ static int run(int argc, char *argv[]) {
|
||||
"list-transfers", "cancel-transfer"))
|
||||
return chainload_importctl(argc, argv);
|
||||
|
||||
r = bus_connect_transport(arg_transport, arg_host, RUNTIME_SCOPE_SYSTEM, &bus);
|
||||
r = bus_connect_transport(arg_transport, arg_host, arg_runtime_scope, &bus);
|
||||
if (r < 0)
|
||||
return bus_log_connect_error(r, arg_transport, RUNTIME_SCOPE_SYSTEM);
|
||||
return bus_log_connect_error(r, arg_transport, arg_runtime_scope);
|
||||
|
||||
(void) sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
|
||||
|
||||
|
||||
@@ -278,22 +278,24 @@ static int machine_add_from_params(
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_ACCESS_DENIED, "Only root may register machines for other users");
|
||||
}
|
||||
|
||||
const char *details[] = {
|
||||
"name", name,
|
||||
"class", machine_class_to_string(c),
|
||||
NULL
|
||||
};
|
||||
if (manager->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
const char *details[] = {
|
||||
"name", name,
|
||||
"class", machine_class_to_string(c),
|
||||
NULL
|
||||
};
|
||||
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
polkit_action,
|
||||
details,
|
||||
&manager->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 0; /* Will call us back */
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
polkit_action,
|
||||
details,
|
||||
&manager->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 0; /* Will call us back */
|
||||
}
|
||||
|
||||
r = manager_add_machine(manager, name, &m);
|
||||
if (r < 0)
|
||||
@@ -697,7 +699,18 @@ static int method_register_machine(sd_bus_message *message, void *userdata, sd_b
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
|
||||
r = cg_pidref_get_unit_full(&m->leader, &m->unit, &m->subgroup);
|
||||
switch (manager->runtime_scope) {
|
||||
case RUNTIME_SCOPE_USER:
|
||||
r = cg_pidref_get_user_unit_full(&m->leader, &m->unit, &m->subgroup);
|
||||
break;
|
||||
|
||||
case RUNTIME_SCOPE_SYSTEM:
|
||||
r = cg_pidref_get_unit_full(&m->leader, &m->unit, &m->subgroup);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
if (r < 0) {
|
||||
r = sd_bus_error_set_errnof(error, r,
|
||||
"Failed to determine unit of process "PID_FMT" : %m",
|
||||
@@ -983,22 +996,24 @@ static int method_clean_pool(sd_bus_message *message, void *userdata, sd_bus_err
|
||||
else
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown mode '%s'.", mm);
|
||||
|
||||
const char *details[] = {
|
||||
"verb", "clean_pool",
|
||||
"mode", mm,
|
||||
NULL
|
||||
};
|
||||
if (m->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
const char *details[] = {
|
||||
"verb", "clean_pool",
|
||||
"mode", mm,
|
||||
NULL
|
||||
};
|
||||
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
details,
|
||||
&m->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
details,
|
||||
&m->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
}
|
||||
|
||||
r = image_clean_pool_operation(m, mode, &operation);
|
||||
if (r < 0)
|
||||
@@ -1022,28 +1037,30 @@ static int method_set_pool_limit(sd_bus_message *message, void *userdata, sd_bus
|
||||
if (!FILE_SIZE_VALID_OR_INFINITY(limit))
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range");
|
||||
|
||||
const char *details[] = {
|
||||
"verb", "set_pool_limit",
|
||||
NULL
|
||||
};
|
||||
if (m->runtime_scope != RUNTIME_SCOPE_USER) {
|
||||
const char *details[] = {
|
||||
"verb", "set_pool_limit",
|
||||
NULL
|
||||
};
|
||||
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
details,
|
||||
&m->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
r = bus_verify_polkit_async(
|
||||
message,
|
||||
"org.freedesktop.machine1.manage-machines",
|
||||
details,
|
||||
&m->polkit_registry,
|
||||
error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
}
|
||||
|
||||
/* Set up the machine directory if necessary */
|
||||
r = setup_machine_directory(error, /* use_btrfs_subvol= */ true, /* use_btrfs_quota= */ true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = image_set_pool_limit(IMAGE_MACHINE, limit);
|
||||
r = image_set_pool_limit(m->runtime_scope, IMAGE_MACHINE, limit);
|
||||
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs.");
|
||||
if (r < 0)
|
||||
@@ -1534,7 +1551,7 @@ int manager_unref_unit(
|
||||
assert(m);
|
||||
assert(unit);
|
||||
|
||||
return bus_call_method(m->bus, bus_systemd_mgr, "UnrefUnit", error, NULL, "s", unit);
|
||||
return bus_call_method(m->api_bus, bus_systemd_mgr, "UnrefUnit", error, NULL, "s", unit);
|
||||
}
|
||||
|
||||
int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
|
||||
@@ -1544,7 +1561,7 @@ int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, c
|
||||
assert(manager);
|
||||
assert(unit);
|
||||
|
||||
r = bus_call_method(manager->bus, bus_systemd_mgr, "StopUnit", error, &reply, "ss", unit, "fail");
|
||||
r = bus_call_method(manager->api_bus, bus_systemd_mgr, "StopUnit", error, &reply, "ss", unit, "fail");
|
||||
if (r < 0) {
|
||||
if (sd_bus_error_has_names(error, BUS_ERROR_NO_SUCH_UNIT,
|
||||
BUS_ERROR_LOAD_FAILED)) {
|
||||
@@ -1582,9 +1599,9 @@ int manager_kill_unit(Manager *manager, const char *unit, const char *subgroup,
|
||||
assert(unit);
|
||||
|
||||
if (empty_or_root(subgroup))
|
||||
return bus_call_method(manager->bus, bus_systemd_mgr, "KillUnit", reterr_error, NULL, "ssi", unit, "all", signo);
|
||||
return bus_call_method(manager->api_bus, bus_systemd_mgr, "KillUnit", reterr_error, NULL, "ssi", unit, "all", signo);
|
||||
|
||||
return bus_call_method(manager->bus, bus_systemd_mgr, "KillUnitSubgroup", reterr_error, NULL, "sssi", unit, "cgroup", subgroup, signo);
|
||||
return bus_call_method(manager->api_bus, bus_systemd_mgr, "KillUnitSubgroup", reterr_error, NULL, "sssi", unit, "cgroup", subgroup, signo);
|
||||
}
|
||||
|
||||
int manager_unit_is_active(Manager *manager, const char *unit, sd_bus_error *reterr_error) {
|
||||
@@ -1602,7 +1619,7 @@ int manager_unit_is_active(Manager *manager, const char *unit, sd_bus_error *ret
|
||||
return -ENOMEM;
|
||||
|
||||
r = sd_bus_get_property(
|
||||
manager->bus,
|
||||
manager->api_bus,
|
||||
"org.freedesktop.systemd1",
|
||||
path,
|
||||
"org.freedesktop.systemd1.Unit",
|
||||
@@ -1638,7 +1655,7 @@ int manager_job_is_active(Manager *manager, const char *path, sd_bus_error *rete
|
||||
assert(path);
|
||||
|
||||
r = sd_bus_get_property(
|
||||
manager->bus,
|
||||
manager->api_bus,
|
||||
"org.freedesktop.systemd1",
|
||||
path,
|
||||
"org.freedesktop.systemd1.Job",
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "machine-varlink.h"
|
||||
#include "machined.h"
|
||||
#include "machined-varlink.h"
|
||||
#include "path-lookup.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "user-util.h"
|
||||
@@ -614,14 +615,15 @@ static int vl_method_open_root_directory(sd_varlink *link, sd_json_variant *para
|
||||
return lookup_machine_and_call_method(link, parameters, flags, userdata, vl_method_open_root_directory_internal);
|
||||
}
|
||||
|
||||
static int list_image_one_and_maybe_read_metadata(sd_varlink *link, Image *image, bool more, AcquireMetadata am) {
|
||||
static int list_image_one_and_maybe_read_metadata(Manager *m, sd_varlink *link, Image *image, bool more, AcquireMetadata am) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(link);
|
||||
assert(image);
|
||||
|
||||
if (should_acquire_metadata(am) && !image->metadata_valid) {
|
||||
r = image_read_metadata(image, &image_policy_container);
|
||||
r = image_read_metadata(image, &image_policy_container, m->runtime_scope);
|
||||
if (r < 0 && am != ACQUIRE_METADATA_GRACEFUL)
|
||||
return log_debug_errno(r, "Failed to read image metadata: %m");
|
||||
if (r < 0)
|
||||
@@ -697,7 +699,7 @@ static int vl_method_list_images(sd_varlink *link, sd_json_variant *parameters,
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to find image: %m");
|
||||
|
||||
return list_image_one_and_maybe_read_metadata(link, found, /* more = */ false, p.acquire_metadata);
|
||||
return list_image_one_and_maybe_read_metadata(m, link, found, /* more = */ false, p.acquire_metadata);
|
||||
}
|
||||
|
||||
if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
|
||||
@@ -711,7 +713,7 @@ static int vl_method_list_images(sd_varlink *link, sd_json_variant *parameters,
|
||||
Image *image, *previous = NULL;
|
||||
HASHMAP_FOREACH(image, images) {
|
||||
if (previous) {
|
||||
r = list_image_one_and_maybe_read_metadata(link, previous, /* more = */ true, p.acquire_metadata);
|
||||
r = list_image_one_and_maybe_read_metadata(m, link, previous, /* more = */ true, p.acquire_metadata);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@@ -720,7 +722,7 @@ static int vl_method_list_images(sd_varlink *link, sd_json_variant *parameters,
|
||||
}
|
||||
|
||||
if (previous)
|
||||
return list_image_one_and_maybe_read_metadata(link, previous, /* more = */ false, p.acquire_metadata);
|
||||
return list_image_one_and_maybe_read_metadata(m, link, previous, /* more = */ false, p.acquire_metadata);
|
||||
|
||||
return sd_varlink_error(link, VARLINK_ERROR_MACHINE_IMAGE_NO_SUCH_IMAGE, NULL);
|
||||
}
|
||||
@@ -733,6 +735,8 @@ static int manager_varlink_init_userdb(Manager *m) {
|
||||
|
||||
if (m->varlink_userdb_server)
|
||||
return 0;
|
||||
if (m->runtime_scope != RUNTIME_SCOPE_SYSTEM) /* no userdb in per-user mode! */
|
||||
return 0;
|
||||
|
||||
r = varlink_server_new(&s, SD_VARLINK_SERVER_ACCOUNT_UID|SD_VARLINK_SERVER_INHERIT_USERDATA, m);
|
||||
if (r < 0)
|
||||
@@ -817,11 +821,20 @@ static int manager_varlink_init_machine(Manager *m) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to bind to passed Varlink sockets: %m");
|
||||
if (r == 0) {
|
||||
r = sd_varlink_server_listen_address(s, "/run/systemd/machine/io.systemd.Machine", 0666 | SD_VARLINK_SERVER_MODE_MKDIR_0755);
|
||||
_cleanup_free_ char *socket_path = NULL;
|
||||
r = runtime_directory_generic(m->runtime_scope, "systemd/machine/io.systemd.Machine", &socket_path);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to determine socket path: %m");
|
||||
|
||||
r = sd_varlink_server_listen_address(s, socket_path, runtime_scope_to_socket_mode(m->runtime_scope) | SD_VARLINK_SERVER_MODE_MKDIR_0755);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to bind to io.systemd.Machine varlink socket: %m");
|
||||
|
||||
r = sd_varlink_server_listen_address(s, "/run/systemd/machine/io.systemd.MachineImage", 0666);
|
||||
socket_path = mfree(socket_path);
|
||||
r = runtime_directory_generic(m->runtime_scope, "systemd/machine/io.systemd.MachineImage", &socket_path);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to determine socket path: %m");
|
||||
r = sd_varlink_server_listen_address(s, socket_path, runtime_scope_to_socket_mode(m->runtime_scope));
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to bind to io.systemd.MachineImage varlink socket: %m");
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "main-func.h"
|
||||
#include "mkdir-label.h"
|
||||
#include "operation.h"
|
||||
#include "path-lookup.h"
|
||||
#include "service-util.h"
|
||||
#include "signal-util.h"
|
||||
#include "socket-util.h"
|
||||
@@ -38,7 +39,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unref);
|
||||
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(machine_hash_ops, char, string_hash_func, string_compare_func, Machine, machine_free);
|
||||
|
||||
static int manager_new(Manager **ret) {
|
||||
static int manager_new(RuntimeScope scope, Manager **ret) {
|
||||
_cleanup_(manager_unrefp) Manager *m = NULL;
|
||||
int r;
|
||||
|
||||
@@ -49,9 +50,13 @@ static int manager_new(Manager **ret) {
|
||||
return -ENOMEM;
|
||||
|
||||
*m = (Manager) {
|
||||
.runtime_scope = RUNTIME_SCOPE_SYSTEM,
|
||||
.runtime_scope = scope,
|
||||
};
|
||||
|
||||
r = runtime_directory_generic(scope, "systemd/machines", &m->state_dir);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
m->machines = hashmap_new(&machine_hash_ops);
|
||||
if (!m->machines)
|
||||
return -ENOMEM;
|
||||
@@ -105,9 +110,12 @@ static Manager* manager_unref(Manager *m) {
|
||||
|
||||
manager_varlink_done(m);
|
||||
|
||||
sd_bus_flush_close_unref(m->bus);
|
||||
sd_bus_flush_close_unref(m->api_bus);
|
||||
sd_bus_flush_close_unref(m->system_bus);
|
||||
sd_event_unref(m->event);
|
||||
|
||||
free(m->state_dir);
|
||||
|
||||
return mfree(m);
|
||||
}
|
||||
|
||||
@@ -118,6 +126,8 @@ static int manager_add_host_machine(Manager *m) {
|
||||
Machine *t;
|
||||
int r;
|
||||
|
||||
if (m->runtime_scope != RUNTIME_SCOPE_SYSTEM)
|
||||
return 0;
|
||||
if (m->host_machine)
|
||||
return 0;
|
||||
|
||||
@@ -174,12 +184,12 @@ static int manager_enumerate_machines(Manager *m) {
|
||||
return r;
|
||||
|
||||
/* Read in machine data stored on disk */
|
||||
d = opendir("/run/systemd/machines");
|
||||
d = opendir(m->state_dir);
|
||||
if (!d) {
|
||||
if (errno == ENOENT)
|
||||
return 0;
|
||||
|
||||
return log_error_errno(errno, "Failed to open %s: %m", "/run/systemd/machines");
|
||||
return log_error_errno(errno, "Failed to open '%s': %m", m->state_dir);
|
||||
}
|
||||
|
||||
FOREACH_DIRENT(de, d, return -errno) {
|
||||
@@ -214,26 +224,45 @@ static int manager_connect_bus(Manager *m) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(!m->bus);
|
||||
assert(!m->system_bus);
|
||||
assert(!m->api_bus);
|
||||
|
||||
r = sd_bus_default_system(&m->bus);
|
||||
r = sd_bus_default_system(&m->system_bus);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to connect to system bus: %m");
|
||||
|
||||
r = bus_add_implementation(m->bus, &manager_object, m);
|
||||
r = sd_bus_attach_event(m->system_bus, m->event, 0);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to attach system bus to event loop: %m");
|
||||
|
||||
if (m->runtime_scope == RUNTIME_SCOPE_SYSTEM)
|
||||
m->api_bus = sd_bus_ref(m->system_bus);
|
||||
else {
|
||||
assert(m->runtime_scope == RUNTIME_SCOPE_USER);
|
||||
|
||||
r = sd_bus_default_user(&m->api_bus);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to connect to user bus: %m");
|
||||
|
||||
r = sd_bus_attach_event(m->api_bus, m->event, 0);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to attach user bus to event loop: %m");
|
||||
}
|
||||
|
||||
r = bus_add_implementation(m->api_bus, &manager_object, m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = bus_match_signal_async(m->bus, NULL, bus_systemd_mgr, "JobRemoved", match_job_removed, NULL, m);
|
||||
r = bus_match_signal_async(m->api_bus, NULL, bus_systemd_mgr, "JobRemoved", match_job_removed, NULL, m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add match for JobRemoved: %m");
|
||||
|
||||
r = bus_match_signal_async(m->bus, NULL, bus_systemd_mgr, "UnitRemoved", match_unit_removed, NULL, m);
|
||||
r = bus_match_signal_async(m->api_bus, NULL, bus_systemd_mgr, "UnitRemoved", match_unit_removed, NULL, m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to request match for UnitRemoved: %m");
|
||||
|
||||
r = sd_bus_match_signal_async(
|
||||
m->bus,
|
||||
m->api_bus,
|
||||
NULL,
|
||||
"org.freedesktop.systemd1",
|
||||
NULL,
|
||||
@@ -243,26 +272,22 @@ static int manager_connect_bus(Manager *m) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to request match for PropertiesChanged: %m");
|
||||
|
||||
r = bus_match_signal_async(m->bus, NULL, bus_systemd_mgr, "Reloading", match_reloading, NULL, m);
|
||||
r = bus_match_signal_async(m->api_bus, NULL, bus_systemd_mgr, "Reloading", match_reloading, NULL, m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to request match for Reloading: %m");
|
||||
|
||||
r = bus_call_method_async(m->bus, NULL, bus_systemd_mgr, "Subscribe", NULL, NULL, NULL);
|
||||
r = bus_call_method_async(m->api_bus, NULL, bus_systemd_mgr, "Subscribe", NULL, NULL, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to enable subscription: %m");
|
||||
|
||||
r = bus_log_control_api_register(m->bus);
|
||||
r = bus_log_control_api_register(m->api_bus);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.machine1", 0, NULL, NULL);
|
||||
r = sd_bus_request_name_async(m->api_bus, NULL, "org.freedesktop.machine1", 0, NULL, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to request name: %m");
|
||||
|
||||
r = sd_bus_attach_event(m->bus, m->event, 0);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to attach bus to event loop: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -315,6 +340,7 @@ static bool check_idle(void *userdata) {
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
_cleanup_(manager_unrefp) Manager *m = NULL;
|
||||
RuntimeScope scope = RUNTIME_SCOPE_SYSTEM;
|
||||
int r;
|
||||
|
||||
log_set_facility(LOG_AUTH);
|
||||
@@ -324,6 +350,7 @@ static int run(int argc, char *argv[]) {
|
||||
"Manage registrations of local VMs and containers.",
|
||||
BUS_IMPLEMENTATIONS(&manager_object,
|
||||
&log_control_object),
|
||||
&scope,
|
||||
argc, argv);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
@@ -333,11 +360,12 @@ static int run(int argc, char *argv[]) {
|
||||
/* Always create the directories people can create inotify watches in. Note that some applications might check
|
||||
* for the existence of /run/systemd/machines/ to determine whether machined is available, so please always
|
||||
* make sure this check stays in. */
|
||||
(void) mkdir_label("/run/systemd/machines", 0755);
|
||||
if (scope == RUNTIME_SCOPE_SYSTEM)
|
||||
(void) mkdir_label("/run/systemd/machines", 0755);
|
||||
|
||||
assert_se(sigprocmask_many(SIG_BLOCK, /* ret_old_mask= */ NULL, SIGCHLD) >= 0);
|
||||
|
||||
r = manager_new(&m);
|
||||
r = manager_new(scope, &m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to allocate manager object: %m");
|
||||
|
||||
@@ -351,7 +379,7 @@ static int run(int argc, char *argv[]) {
|
||||
|
||||
r = bus_event_loop_with_idle(
|
||||
m->event,
|
||||
m->bus,
|
||||
m->api_bus,
|
||||
"org.freedesktop.machine1",
|
||||
DEFAULT_EXIT_USEC,
|
||||
check_idle, m);
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
|
||||
typedef struct Manager {
|
||||
sd_event *event;
|
||||
sd_bus *bus;
|
||||
sd_bus *api_bus; /* this is where we offer our services */
|
||||
sd_bus *system_bus; /* this is where we talk to system services on, for example PK or so */
|
||||
|
||||
Hashmap *machines;
|
||||
Hashmap *machines_by_unit; /* This hashmap only tracks machines where a system-level encapsulates
|
||||
@@ -32,7 +33,8 @@ typedef struct Manager {
|
||||
sd_varlink_server *varlink_userdb_server;
|
||||
sd_varlink_server *varlink_machine_server;
|
||||
|
||||
RuntimeScope runtime_scope; /* for now: always RUNTIME_SCOPE_SYSTEM */
|
||||
RuntimeScope runtime_scope;
|
||||
char *state_dir;
|
||||
} Manager;
|
||||
|
||||
int manager_add_machine(Manager *m, const char *name, Machine **ret);
|
||||
|
||||
@@ -49,5 +49,8 @@ install_data('org.freedesktop.machine1.conf',
|
||||
install_dir : dbuspolicydir)
|
||||
install_data('org.freedesktop.machine1.service',
|
||||
install_dir : dbussystemservicedir)
|
||||
install_data('org.freedesktop.machine1.service-for-session',
|
||||
install_dir : dbussessionservicedir,
|
||||
rename : 'org.freedesktop.machine1.service')
|
||||
install_data('org.freedesktop.machine1.policy',
|
||||
install_dir : polkitpolicydir)
|
||||
|
||||
13
src/machine/org.freedesktop.machine1.service-for-session
Normal file
13
src/machine/org.freedesktop.machine1.service-for-session
Normal file
@@ -0,0 +1,13 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
[D-BUS Service]
|
||||
Name=org.freedesktop.machine1
|
||||
Exec=/bin/false
|
||||
SystemdService=dbus-org.freedesktop.machine1.service
|
||||
@@ -29,6 +29,7 @@ static int run(int argc, char *argv[]) {
|
||||
r = service_parse_argv("systemd-networkd.service",
|
||||
"Manage and configure network devices, create virtual network devices",
|
||||
BUS_IMPLEMENTATIONS(&manager_object, &log_control_object),
|
||||
/* runtime_scope= */ NULL,
|
||||
argc, argv);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
@@ -6055,6 +6055,7 @@ static int run(int argc, char *argv[]) {
|
||||
/* We take an exclusive lock on this image, since it's our private, ephemeral copy
|
||||
* only owned by us and no one else. */
|
||||
r = image_path_lock(
|
||||
arg_privileged ? RUNTIME_SCOPE_SYSTEM : RUNTIME_SCOPE_USER,
|
||||
np,
|
||||
LOCK_EX|LOCK_NB,
|
||||
arg_privileged ? &tree_global_lock : NULL,
|
||||
@@ -6091,6 +6092,7 @@ static int run(int argc, char *argv[]) {
|
||||
goto finish;
|
||||
|
||||
r = image_path_lock(
|
||||
arg_privileged ? RUNTIME_SCOPE_SYSTEM : RUNTIME_SCOPE_USER,
|
||||
arg_directory,
|
||||
(arg_read_only ? LOCK_SH : LOCK_EX) | LOCK_NB,
|
||||
arg_privileged ? &tree_global_lock : NULL,
|
||||
@@ -6218,6 +6220,7 @@ static int run(int argc, char *argv[]) {
|
||||
|
||||
/* Always take an exclusive lock on our own ephemeral copy. */
|
||||
r = image_path_lock(
|
||||
arg_privileged ? RUNTIME_SCOPE_SYSTEM : RUNTIME_SCOPE_USER,
|
||||
np,
|
||||
LOCK_EX|LOCK_NB,
|
||||
arg_privileged ? &tree_global_lock : NULL,
|
||||
@@ -6245,6 +6248,7 @@ static int run(int argc, char *argv[]) {
|
||||
remove_image = true;
|
||||
} else {
|
||||
r = image_path_lock(
|
||||
arg_privileged ? RUNTIME_SCOPE_SYSTEM : RUNTIME_SCOPE_USER,
|
||||
arg_image,
|
||||
(arg_read_only ? LOCK_SH : LOCK_EX) | LOCK_NB,
|
||||
arg_privileged ? &tree_global_lock : NULL,
|
||||
|
||||
@@ -61,7 +61,7 @@ int bus_image_common_get_os_release(
|
||||
return 1;
|
||||
|
||||
if (!image->metadata_valid) {
|
||||
r = image_read_metadata(image, &image_policy_service);
|
||||
r = image_read_metadata(image, &image_policy_service, m->runtime_scope);
|
||||
if (r < 0)
|
||||
return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m");
|
||||
}
|
||||
@@ -539,7 +539,7 @@ int bus_image_common_remove(
|
||||
if (r == 0) {
|
||||
errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
|
||||
|
||||
r = image_remove(image);
|
||||
r = image_remove(image, m->runtime_scope);
|
||||
if (r < 0) {
|
||||
(void) write(errno_pipe_fd[1], &r, sizeof(r));
|
||||
_exit(EXIT_FAILURE);
|
||||
@@ -801,7 +801,7 @@ int bus_image_common_mark_read_only(
|
||||
if (r == 0)
|
||||
return 1; /* Will call us back */
|
||||
|
||||
r = image_read_only(image, read_only);
|
||||
r = image_read_only(image, read_only, m->runtime_scope);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@@ -133,6 +133,7 @@ static int run(int argc, char *argv[]) {
|
||||
"Manage registrations of portable images.",
|
||||
BUS_IMPLEMENTATIONS(&manager_object,
|
||||
&log_control_object),
|
||||
/* runtime_scope= */ NULL,
|
||||
argc, argv);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
@@ -30,6 +30,7 @@ static int run(int argc, char *argv[]) {
|
||||
"Provide name resolution with caching using DNS, mDNS, LLMNR.",
|
||||
BUS_IMPLEMENTATIONS(&manager_object,
|
||||
&log_control_object),
|
||||
/* runtime_scope= */ NULL,
|
||||
argc, argv);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "chase.h"
|
||||
#include "chattr-util.h"
|
||||
#include "copy.h"
|
||||
#include "devnum-util.h"
|
||||
#include "dirent-util.h"
|
||||
#include "discover-image.h"
|
||||
#include "dissect-image.h"
|
||||
@@ -37,6 +38,7 @@
|
||||
#include "mkdir.h"
|
||||
#include "nulstr-util.h"
|
||||
#include "os-util.h"
|
||||
#include "path-lookup.h"
|
||||
#include "path-util.h"
|
||||
#include "rm-rf.h"
|
||||
#include "runtime-scope.h"
|
||||
@@ -119,6 +121,15 @@ static const char *const image_root_runtime_table[_IMAGE_CLASS_MAX] = {
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(image_root_runtime, ImageClass);
|
||||
|
||||
static const char *const image_dirname_table[_IMAGE_CLASS_MAX] = {
|
||||
[IMAGE_MACHINE] = "machines",
|
||||
[IMAGE_PORTABLE] = "portables",
|
||||
[IMAGE_SYSEXT] = "extensions",
|
||||
[IMAGE_CONFEXT] = "confexts",
|
||||
};
|
||||
|
||||
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(image_dirname, ImageClass);
|
||||
|
||||
static Image* image_free(Image *i) {
|
||||
assert(i);
|
||||
|
||||
@@ -138,7 +149,7 @@ DEFINE_TRIVIAL_REF_UNREF_FUNC(Image, image, image_free);
|
||||
DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(image_hash_ops, char, string_hash_func, string_compare_func,
|
||||
Image, image_unref);
|
||||
|
||||
static char** image_settings_path(Image *image) {
|
||||
static char** image_settings_path(Image *image, RuntimeScope scope) {
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
_cleanup_free_ char *fn = NULL;
|
||||
size_t i = 0;
|
||||
@@ -146,7 +157,7 @@ static char** image_settings_path(Image *image) {
|
||||
|
||||
assert(image);
|
||||
|
||||
l = new0(char*, 4);
|
||||
l = new0(char*, 5);
|
||||
if (!l)
|
||||
return NULL;
|
||||
|
||||
@@ -154,7 +165,41 @@ static char** image_settings_path(Image *image) {
|
||||
if (!fn)
|
||||
return NULL;
|
||||
|
||||
FOREACH_STRING(s, "/etc/systemd/nspawn", "/run/systemd/nspawn") {
|
||||
static const uint64_t system_locations[] = {
|
||||
SD_PATH_SYSTEM_CONFIGURATION,
|
||||
SD_PATH_SYSTEM_RUNTIME,
|
||||
SD_PATH_SYSTEM_LIBRARY_PRIVATE,
|
||||
UINT64_MAX
|
||||
};
|
||||
static const uint64_t user_locations[] = {
|
||||
SD_PATH_USER_CONFIGURATION,
|
||||
SD_PATH_USER_RUNTIME,
|
||||
SD_PATH_USER_LIBRARY_PRIVATE,
|
||||
UINT64_MAX
|
||||
};
|
||||
const uint64_t *locations;
|
||||
|
||||
switch (scope) {
|
||||
case RUNTIME_SCOPE_SYSTEM:
|
||||
locations = system_locations;
|
||||
break;
|
||||
|
||||
case RUNTIME_SCOPE_USER:
|
||||
locations = user_locations;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
for (size_t k = 0; locations[k] != UINT64_MAX; k++) {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
r = sd_path_lookup(locations[k], "systemd/nspawn", &s);
|
||||
if (r == -ENXIO)
|
||||
continue;
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
|
||||
l[i] = path_join(s, fn);
|
||||
if (!l[i])
|
||||
return NULL;
|
||||
@@ -1086,7 +1131,7 @@ int image_discover(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int image_remove(Image *i) {
|
||||
int image_remove(Image *i, RuntimeScope scope) {
|
||||
_cleanup_(release_lock_file) LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT;
|
||||
_cleanup_strv_free_ char **settings = NULL;
|
||||
_cleanup_free_ char *roothash = NULL;
|
||||
@@ -1097,7 +1142,7 @@ int image_remove(Image *i) {
|
||||
if (image_is_vendor(i) || image_is_host(i))
|
||||
return -EROFS;
|
||||
|
||||
settings = image_settings_path(i);
|
||||
settings = image_settings_path(i, scope);
|
||||
if (!settings)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -1106,7 +1151,7 @@ int image_remove(Image *i) {
|
||||
return r;
|
||||
|
||||
/* Make sure we don't interfere with a running nspawn */
|
||||
r = image_path_lock(i->path, LOCK_EX|LOCK_NB, &global_lock, &local_lock);
|
||||
r = image_path_lock(scope, i->path, LOCK_EX|LOCK_NB, &global_lock, &local_lock);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -1192,7 +1237,7 @@ int image_rename(Image *i, const char *new_name, RuntimeScope scope) {
|
||||
if (image_is_vendor(i) || image_is_host(i))
|
||||
return -EROFS;
|
||||
|
||||
settings = image_settings_path(i);
|
||||
settings = image_settings_path(i, scope);
|
||||
if (!settings)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -1201,14 +1246,14 @@ int image_rename(Image *i, const char *new_name, RuntimeScope scope) {
|
||||
return r;
|
||||
|
||||
/* Make sure we don't interfere with a running nspawn */
|
||||
r = image_path_lock(i->path, LOCK_EX|LOCK_NB, &global_lock, &local_lock);
|
||||
r = image_path_lock(scope, i->path, LOCK_EX|LOCK_NB, &global_lock, &local_lock);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Make sure nobody takes the new name, between the time we
|
||||
* checked it is currently unused in all search paths, and the
|
||||
* time we take possession of it */
|
||||
r = image_name_lock(new_name, LOCK_EX|LOCK_NB, &name_lock);
|
||||
r = image_name_lock(scope, new_name, LOCK_EX|LOCK_NB, &name_lock);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -1299,11 +1344,64 @@ static int clone_auxiliary_file(const char *path, const char *new_name, const ch
|
||||
return copy_file_atomic(path, rs, 0664, COPY_REFLINK);
|
||||
}
|
||||
|
||||
static int get_pool_directory(
|
||||
RuntimeScope scope,
|
||||
ImageClass class,
|
||||
const char *fname,
|
||||
const char *suffix,
|
||||
char **ret) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(scope >= 0);
|
||||
assert(scope < _RUNTIME_SCOPE_MAX);
|
||||
assert(class >= 0);
|
||||
assert(class < _IMAGE_CLASS_MAX);
|
||||
assert(ret);
|
||||
|
||||
_cleanup_free_ char *root = NULL;
|
||||
switch (scope) {
|
||||
|
||||
case RUNTIME_SCOPE_SYSTEM:
|
||||
r = sd_path_lookup(SD_PATH_SYSTEM_STATE_PRIVATE, /* suffix= */ NULL, &root);
|
||||
break;
|
||||
|
||||
case RUNTIME_SCOPE_USER:
|
||||
r = sd_path_lookup(SD_PATH_USER_STATE_PRIVATE, /* suffix= */ NULL, &root);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
const char *n = image_dirname_to_string(class);
|
||||
if (!n)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
_cleanup_free_ char *j = NULL;
|
||||
const char *fn;
|
||||
if (fname && suffix) {
|
||||
j = strjoin(fname, suffix);
|
||||
if (!j)
|
||||
return -ENOMEM;
|
||||
fn = j;
|
||||
} else
|
||||
fn = fname ?: suffix;
|
||||
|
||||
_cleanup_free_ char *p = path_join(root, n, fn);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
*ret = TAKE_PTR(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int image_clone(Image *i, const char *new_name, bool read_only, RuntimeScope scope) {
|
||||
_cleanup_(release_lock_file) LockFile name_lock = LOCK_FILE_INIT;
|
||||
_cleanup_strv_free_ char **settings = NULL;
|
||||
_cleanup_free_ char *roothash = NULL;
|
||||
const char *new_path;
|
||||
int r;
|
||||
|
||||
assert(i);
|
||||
@@ -1311,7 +1409,7 @@ int image_clone(Image *i, const char *new_name, bool read_only, RuntimeScope sco
|
||||
if (!image_name_is_valid(new_name))
|
||||
return -EINVAL;
|
||||
|
||||
settings = image_settings_path(i);
|
||||
settings = image_settings_path(i, scope);
|
||||
if (!settings)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -1322,11 +1420,11 @@ int image_clone(Image *i, const char *new_name, bool read_only, RuntimeScope sco
|
||||
/* Make sure nobody takes the new name, between the time we
|
||||
* checked it is currently unused in all search paths, and the
|
||||
* time we take possession of it */
|
||||
r = image_name_lock(new_name, LOCK_EX|LOCK_NB, &name_lock);
|
||||
r = image_name_lock(scope, new_name, LOCK_EX|LOCK_NB, &name_lock);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = image_find(scope, IMAGE_MACHINE, new_name, NULL, NULL);
|
||||
r = image_find(scope, i->class, new_name, NULL, NULL);
|
||||
if (r >= 0)
|
||||
return -EEXIST;
|
||||
if (r != -ENOENT)
|
||||
@@ -1335,11 +1433,14 @@ int image_clone(Image *i, const char *new_name, bool read_only, RuntimeScope sco
|
||||
switch (i->type) {
|
||||
|
||||
case IMAGE_SUBVOLUME:
|
||||
case IMAGE_DIRECTORY:
|
||||
case IMAGE_DIRECTORY: {
|
||||
/* If we can we'll always try to create a new btrfs subvolume here, even if the source is a plain
|
||||
* directory. */
|
||||
|
||||
new_path = strjoina("/var/lib/machines/", new_name);
|
||||
_cleanup_free_ char *new_path = NULL;
|
||||
r = get_pool_directory(scope, i->class, new_name, /* suffix= */ NULL, &new_path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = btrfs_subvol_snapshot_at(AT_FDCWD, i->path, AT_FDCWD, new_path,
|
||||
(read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) |
|
||||
@@ -1353,19 +1454,23 @@ int image_clone(Image *i, const char *new_name, bool read_only, RuntimeScope sco
|
||||
(void) btrfs_subvol_auto_qgroup(new_path, 0, true);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case IMAGE_RAW:
|
||||
new_path = strjoina("/var/lib/machines/", new_name, ".raw");
|
||||
case IMAGE_RAW: {
|
||||
_cleanup_free_ char *new_path = NULL;
|
||||
r = get_pool_directory(scope, i->class, new_name, ".raw", &new_path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = copy_file_atomic(i->path, new_path, read_only ? 0444 : 0644,
|
||||
COPY_REFLINK|COPY_CRTIME|COPY_NOCOW_AFTER);
|
||||
break;
|
||||
}
|
||||
|
||||
case IMAGE_BLOCK:
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -1382,7 +1487,7 @@ int image_clone(Image *i, const char *new_name, bool read_only, RuntimeScope sco
|
||||
return 0;
|
||||
}
|
||||
|
||||
int image_read_only(Image *i, bool b) {
|
||||
int image_read_only(Image *i, bool b, RuntimeScope scope) {
|
||||
_cleanup_(release_lock_file) LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT;
|
||||
int r;
|
||||
|
||||
@@ -1392,7 +1497,7 @@ int image_read_only(Image *i, bool b) {
|
||||
return -EROFS;
|
||||
|
||||
/* Make sure we don't interfere with a running nspawn */
|
||||
r = image_path_lock(i->path, LOCK_EX|LOCK_NB, &global_lock, &local_lock);
|
||||
r = image_path_lock(scope, i->path, LOCK_EX|LOCK_NB, &global_lock, &local_lock);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -1469,12 +1574,33 @@ int image_read_only(Image *i, bool b) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void make_lock_dir(void) {
|
||||
(void) mkdir_p("/run/systemd/nspawn", 0755);
|
||||
(void) mkdir("/run/systemd/nspawn/locks", 0700);
|
||||
static int make_lock_dir(RuntimeScope scope) {
|
||||
int r;
|
||||
|
||||
_cleanup_free_ char *p = NULL;
|
||||
r = runtime_directory_generic(scope, "systemd", &p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_close_ int pfd = open_mkdir_at(AT_FDCWD, p, O_CLOEXEC, 0755);
|
||||
if (pfd < 0)
|
||||
return pfd;
|
||||
|
||||
_cleanup_close_ int nfd = open_mkdir_at(pfd, "nspawn", O_CLOEXEC, 0755);
|
||||
if (nfd < 0)
|
||||
return nfd;
|
||||
|
||||
r = RET_NERRNO(mkdirat(nfd, "locks", 0700));
|
||||
if (r == -EEXIST)
|
||||
return 0;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int image_path_lock(
|
||||
RuntimeScope scope,
|
||||
const char *path,
|
||||
int operation,
|
||||
LockFile *ret_global,
|
||||
@@ -1490,7 +1616,7 @@ int image_path_lock(
|
||||
assert(ret_local);
|
||||
|
||||
/* Locks an image path. This actually creates two locks: one "local" one, next to the image path
|
||||
* itself, which might be shared via NFS. And another "global" one, in /run, that uses the
|
||||
* itself, which might be shared via NFS. And another "global" one, in /run/, that uses the
|
||||
* device/inode number. This has the benefit that we can even lock a tree that is a mount point,
|
||||
* correctly. */
|
||||
|
||||
@@ -1534,15 +1660,21 @@ int image_path_lock(
|
||||
}
|
||||
|
||||
if (ret_global) {
|
||||
if (stat(path, &st) >= 0) {
|
||||
if (stat(path, &st) < 0)
|
||||
log_debug_errno(errno, "Failed to stat() image '%s', not locking image: %m", path);
|
||||
else {
|
||||
r = runtime_directory_generic(scope, "systemd/nspawn/locks/", &p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (S_ISBLK(st.st_mode))
|
||||
r = asprintf(&p, "/run/systemd/nspawn/locks/block-%u:%u", major(st.st_rdev), minor(st.st_rdev));
|
||||
r = strextendf(&p, "block-" DEVNUM_FORMAT_STR, DEVNUM_FORMAT_VAL(st.st_rdev));
|
||||
else if (S_ISDIR(st.st_mode) || S_ISREG(st.st_mode))
|
||||
r = asprintf(&p, "/run/systemd/nspawn/locks/inode-%lu:%lu", (unsigned long) st.st_dev, (unsigned long) st.st_ino);
|
||||
r = strextendf(&p, "inode-%" PRIu64 ":%" PRIu64, (uint64_t) st.st_dev, (uint64_t) st.st_ino);
|
||||
else
|
||||
return -ENOTTY;
|
||||
if (r < 0)
|
||||
return -ENOMEM;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1551,15 +1683,15 @@ int image_path_lock(
|
||||
if (!path_startswith(path, "/dev/")) {
|
||||
r = make_lock_file_for(path, operation, &t);
|
||||
if (r < 0) {
|
||||
if (!exclusive && r == -EROFS)
|
||||
log_debug_errno(r, "Failed to create shared lock for '%s', ignoring: %m", path);
|
||||
else
|
||||
if (exclusive || r != -EROFS)
|
||||
return r;
|
||||
|
||||
log_debug_errno(r, "Failed to create shared lock for '%s', ignoring: %m", path);
|
||||
}
|
||||
}
|
||||
|
||||
if (p) {
|
||||
make_lock_dir();
|
||||
(void) make_lock_dir(scope);
|
||||
|
||||
r = make_lock_file(p, operation, ret_global);
|
||||
if (r < 0) {
|
||||
@@ -1599,36 +1731,39 @@ int image_set_limit(Image *i, uint64_t referenced_max) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int image_set_pool_limit(ImageClass class, uint64_t referenced_max) {
|
||||
const char *dir;
|
||||
int image_set_pool_limit(RuntimeScope scope, ImageClass class, uint64_t referenced_max) {
|
||||
int r;
|
||||
|
||||
assert(scope >= 0 && scope < _RUNTIME_SCOPE_MAX);
|
||||
assert(class >= 0 && class < _IMAGE_CLASS_MAX);
|
||||
|
||||
dir = image_root_to_string(class);
|
||||
_cleanup_free_ char *pool = NULL;
|
||||
r = get_pool_directory(scope, class, /* fname= */ NULL, /* suffix= */ NULL, &pool);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = btrfs_qgroup_set_limit(dir, /* qgroupid = */ 0, referenced_max);
|
||||
r = btrfs_qgroup_set_limit(pool, /* qgroupid = */ 0, referenced_max);
|
||||
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
|
||||
return r;
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to set limit on btrfs quota group for '%s', ignoring: %m", dir);
|
||||
log_debug_errno(r, "Failed to set limit on btrfs quota group for '%s', ignoring: %m", pool);
|
||||
|
||||
r = btrfs_subvol_set_subtree_quota_limit(dir, /* subvol_id = */ 0, referenced_max);
|
||||
r = btrfs_subvol_set_subtree_quota_limit(pool, /* subvol_id = */ 0, referenced_max);
|
||||
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
|
||||
return r;
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to set subtree quota limit for '%s': %m", dir);
|
||||
return log_debug_errno(r, "Failed to set subtree quota limit for '%s': %m", pool);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int image_read_metadata(Image *i, const ImagePolicy *image_policy) {
|
||||
int image_read_metadata(Image *i, const ImagePolicy *image_policy, RuntimeScope scope) {
|
||||
_cleanup_(release_lock_file) LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT;
|
||||
int r;
|
||||
|
||||
assert(i);
|
||||
|
||||
r = image_path_lock(i->path, LOCK_SH|LOCK_NB, &global_lock, &local_lock);
|
||||
r = image_path_lock(scope, i->path, LOCK_SH|LOCK_NB, &global_lock, &local_lock);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -1758,8 +1893,13 @@ int image_read_metadata(Image *i, const ImagePolicy *image_policy) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int image_name_lock(const char *name, int operation, LockFile *ret) {
|
||||
const char *p;
|
||||
int image_name_lock(
|
||||
RuntimeScope scope,
|
||||
const char *name,
|
||||
int operation,
|
||||
LockFile *ret) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(name);
|
||||
assert(ret);
|
||||
@@ -1777,9 +1917,16 @@ int image_name_lock(const char *name, int operation, LockFile *ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
make_lock_dir();
|
||||
(void) make_lock_dir(scope);
|
||||
|
||||
_cleanup_free_ char *p = NULL;
|
||||
r = runtime_directory_generic(scope, "systemd/nspawn/locks/name-", &p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!strextend(&p, name))
|
||||
return -ENOMEM;
|
||||
|
||||
p = strjoina("/run/systemd/nspawn/locks/name-", name);
|
||||
return make_lock_file(p, operation, ret);
|
||||
}
|
||||
|
||||
|
||||
@@ -55,21 +55,21 @@ int image_from_path(const char *path, Image **ret);
|
||||
int image_find_harder(RuntimeScope scope, ImageClass class, const char *name_or_path, const char *root, Image **ret);
|
||||
int image_discover(RuntimeScope scope, ImageClass class, const char *root, Hashmap **images);
|
||||
|
||||
int image_remove(Image *i);
|
||||
int image_remove(Image *i, RuntimeScope scope);
|
||||
int image_rename(Image *i, const char *new_name, RuntimeScope scope);
|
||||
int image_clone(Image *i, const char *new_name, bool read_only, RuntimeScope scope);
|
||||
int image_read_only(Image *i, bool b);
|
||||
int image_read_only(Image *i, bool b, RuntimeScope scope);
|
||||
|
||||
const char* image_type_to_string(ImageType t) _const_;
|
||||
ImageType image_type_from_string(const char *s) _pure_;
|
||||
|
||||
int image_path_lock(const char *path, int operation, LockFile *global, LockFile *local);
|
||||
int image_name_lock(const char *name, int operation, LockFile *ret);
|
||||
int image_path_lock(RuntimeScope scope, const char *path, int operation, LockFile *global, LockFile *local);
|
||||
int image_name_lock(RuntimeScope scope, const char *name, int operation, LockFile *ret);
|
||||
|
||||
int image_set_limit(Image *i, uint64_t referenced_max);
|
||||
int image_set_pool_limit(ImageClass class, uint64_t referenced_max);
|
||||
int image_set_pool_limit(RuntimeScope scope, ImageClass class, uint64_t referenced_max);
|
||||
|
||||
int image_read_metadata(Image *i, const ImagePolicy *image_policy);
|
||||
int image_read_metadata(Image *i, const ImagePolicy *image_policy, RuntimeScope scope);
|
||||
|
||||
bool image_in_search_path(RuntimeScope scope, ImageClass class, const char *root, const char *image);
|
||||
|
||||
|
||||
@@ -8,9 +8,19 @@
|
||||
#include "bus-object.h"
|
||||
#include "log.h"
|
||||
#include "pretty-print.h"
|
||||
#include "runtime-scope.h"
|
||||
#include "service-util.h"
|
||||
|
||||
static int help(const char *program_path, const char *service, const char *description, bool bus_introspect) {
|
||||
typedef enum HelpFlags {
|
||||
HELP_WITH_BUS_INTROSPECT = 1 << 0,
|
||||
HELP_WITH_RUNTIME_SCOPE = 1 << 1,
|
||||
} HelpFlags;
|
||||
|
||||
static int help(const char *program_path,
|
||||
const char *service,
|
||||
const char *description,
|
||||
HelpFlags flags) {
|
||||
|
||||
_cleanup_free_ char *link = NULL;
|
||||
int r;
|
||||
|
||||
@@ -25,6 +35,7 @@ static int help(const char *program_path, const char *service, const char *descr
|
||||
" -h --help Show this help\n"
|
||||
" --version Show package version\n"
|
||||
"%8$s"
|
||||
"%9$s"
|
||||
"\nSee the %2$s for details.\n",
|
||||
program_path,
|
||||
link,
|
||||
@@ -33,7 +44,9 @@ static int help(const char *program_path, const char *service, const char *descr
|
||||
ansi_highlight(),
|
||||
ansi_normal(),
|
||||
description,
|
||||
bus_introspect ? " --bus-introspect=PATH Write D-Bus XML introspection data\n" : "");
|
||||
FLAGS_SET(flags, HELP_WITH_BUS_INTROSPECT) ? " --bus-introspect=PATH Write D-Bus XML introspection data\n" : "",
|
||||
FLAGS_SET(flags, HELP_WITH_RUNTIME_SCOPE) ? " --system Start service in system mode\n"
|
||||
" --user Start service in user mode\n" : "");
|
||||
|
||||
return 0; /* No further action */
|
||||
}
|
||||
@@ -42,17 +55,22 @@ int service_parse_argv(
|
||||
const char *service,
|
||||
const char *description,
|
||||
const BusObjectImplementation* const* bus_objects,
|
||||
RuntimeScope *runtime_scope,
|
||||
int argc, char *argv[]) {
|
||||
|
||||
enum {
|
||||
ARG_VERSION = 0x100,
|
||||
ARG_BUS_INTROSPECT,
|
||||
ARG_SYSTEM,
|
||||
ARG_USER,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, ARG_VERSION },
|
||||
{ "bus-introspect", required_argument, NULL, ARG_BUS_INTROSPECT },
|
||||
{ "system", no_argument, NULL, ARG_SYSTEM },
|
||||
{ "user", no_argument, NULL, ARG_USER },
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -65,7 +83,11 @@ int service_parse_argv(
|
||||
switch (c) {
|
||||
|
||||
case 'h':
|
||||
return help(argv[0], service, description, bus_objects);
|
||||
return help(argv[0],
|
||||
service,
|
||||
description,
|
||||
(bus_objects ? HELP_WITH_BUS_INTROSPECT : 0) |
|
||||
(runtime_scope ? HELP_WITH_RUNTIME_SCOPE : 0));
|
||||
|
||||
case ARG_VERSION:
|
||||
return version();
|
||||
@@ -76,6 +98,14 @@ int service_parse_argv(
|
||||
optarg,
|
||||
bus_objects);
|
||||
|
||||
case ARG_SYSTEM:
|
||||
case ARG_USER:
|
||||
if (!runtime_scope)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This service cannot be run in --system or --user mode, refusing.");
|
||||
|
||||
*runtime_scope = c == ARG_SYSTEM ? RUNTIME_SCOPE_SYSTEM : RUNTIME_SCOPE_USER;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
@@ -7,4 +7,5 @@ int service_parse_argv(
|
||||
const char *service,
|
||||
const char *description,
|
||||
const BusObjectImplementation* const* bus_objects,
|
||||
RuntimeScope *runtime_scope,
|
||||
int argc, char *argv[]);
|
||||
|
||||
@@ -2127,7 +2127,7 @@ static int image_discover_and_read_metadata(ImageClass image_class, Hashmap **re
|
||||
return log_error_errno(r, "Failed to discover images: %m");
|
||||
|
||||
HASHMAP_FOREACH(img, images) {
|
||||
r = image_read_metadata(img, image_class_info[image_class].default_image_policy);
|
||||
r = image_read_metadata(img, image_class_info[image_class].default_image_policy, RUNTIME_SCOPE_SYSTEM);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read metadata for image %s: %m", img->name);
|
||||
}
|
||||
|
||||
@@ -2079,6 +2079,7 @@ static int run(int argc, char *argv[]) {
|
||||
"System update management service.",
|
||||
BUS_IMPLEMENTATIONS(&manager_object,
|
||||
&log_control_object),
|
||||
/* runtime_scope= */ NULL,
|
||||
argc, argv);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
@@ -1164,6 +1164,7 @@ static int run(int argc, char *argv[]) {
|
||||
"Manage the system clock and timezone and NTP enablement.",
|
||||
BUS_IMPLEMENTATIONS(&manager_object,
|
||||
&log_control_object),
|
||||
/* runtime_scope= */ NULL,
|
||||
argc, argv);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
@@ -151,6 +151,7 @@ static int run(int argc, char *argv[]) {
|
||||
r = service_parse_argv("systemd-timesyncd.service",
|
||||
"Network time synchronization",
|
||||
BUS_IMPLEMENTATIONS(&manager_object, &log_control_object),
|
||||
/* runtime_scope= */ NULL,
|
||||
argc, argv);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
Description=Virtual Machine and Container Registration Service
|
||||
Documentation=man:systemd-machined.service(8)
|
||||
Documentation=man:org.freedesktop.machine1(5)
|
||||
|
||||
Wants=machine.slice
|
||||
After=machine.slice
|
||||
RequiresMountsFor=/var/lib/machines
|
||||
|
||||
@@ -18,6 +18,16 @@ units = [
|
||||
'file' : 'machines.target',
|
||||
'conditions' : ['ENABLE_MACHINED'],
|
||||
},
|
||||
{
|
||||
'file' : 'systemd-machined.service.in',
|
||||
'conditions' : ['ENABLE_MACHINED'],
|
||||
'symlinks' : ['dbus-org.freedesktop.machine1.service'],
|
||||
},
|
||||
{
|
||||
'file' : 'systemd-machined.socket',
|
||||
'conditions' : ['ENABLE_MACHINED'],
|
||||
'symlinks' : ['sockets.target.wants/'],
|
||||
},
|
||||
{ 'file' : 'paths.target' },
|
||||
{ 'file' : 'printer.target' },
|
||||
{ 'file' : 'session.slice' },
|
||||
|
||||
28
units/user/systemd-machined.service.in
Normal file
28
units/user/systemd-machined.service.in
Normal file
@@ -0,0 +1,28 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
[Unit]
|
||||
Description=Virtual Machine and Container Registration Service
|
||||
Documentation=man:systemd-machined.service(8)
|
||||
Documentation=man:org.freedesktop.machine1(5)
|
||||
Wants=machine.slice
|
||||
After=machine.slice
|
||||
|
||||
[Service]
|
||||
BusName=org.freedesktop.machine1
|
||||
ExecStart={{LIBEXECDIR}}/systemd-machined --user
|
||||
LockPersonality=yes
|
||||
MemoryDenyWriteExecute=yes
|
||||
NoNewPrivileges=yes
|
||||
RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
|
||||
RestrictRealtime=yes
|
||||
SystemCallArchitectures=native
|
||||
SystemCallErrorNumber=EPERM
|
||||
SystemCallFilter=@system-service @mount
|
||||
{{SERVICE_WATCHDOG}}
|
||||
18
units/user/systemd-machined.socket
Normal file
18
units/user/systemd-machined.socket
Normal file
@@ -0,0 +1,18 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
[Unit]
|
||||
Description=Virtual Machine and Container Registration Service Socket
|
||||
Documentation=man:systemd-machined.service(8)
|
||||
|
||||
[Socket]
|
||||
ListenStream=%t/systemd/machine/io.systemd.Machine
|
||||
ListenStream=%t/systemd/machine/io.systemd.MachineImage
|
||||
FileDescriptorName=varlink
|
||||
SocketMode=0600
|
||||
Reference in New Issue
Block a user