tree-wide: hook up image dissection policy logic everywhere
This commit is contained in:
@@ -1156,6 +1156,30 @@ static int bus_property_get_exec_dir_symlink(
|
||||
return sd_bus_message_close_container(reply);
|
||||
}
|
||||
|
||||
static int property_get_image_policy(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
ImagePolicy **pp = ASSERT_PTR(userdata);
|
||||
_cleanup_free_ char *s = NULL;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
assert(property);
|
||||
assert(reply);
|
||||
|
||||
r = image_policy_to_string(*pp ?: &image_policy_service, /* simplify= */ true, &s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return sd_bus_message_append(reply, "s", s);
|
||||
}
|
||||
|
||||
const sd_bus_vtable bus_exec_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
@@ -1324,6 +1348,9 @@ const sd_bus_vtable bus_exec_vtable[] = {
|
||||
SD_BUS_PROPERTY("ProtectHostname", "b", bus_property_get_bool, offsetof(ExecContext, protect_hostname), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("NetworkNamespacePath", "s", NULL, offsetof(ExecContext, network_namespace_path), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("IPCNamespacePath", "s", NULL, offsetof(ExecContext, ipc_namespace_path), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RootImagePolicy", "s", property_get_image_policy, offsetof(ExecContext, root_image_policy), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("MountImagePolicy", "s", property_get_image_policy, offsetof(ExecContext, mount_image_policy), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("ExtensionImagePolicy", "s", property_get_image_policy, offsetof(ExecContext, extension_image_policy), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
|
||||
/* Obsolete/redundant properties: */
|
||||
SD_BUS_PROPERTY("Capabilities", "s", property_get_empty_string, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
|
||||
@@ -3900,6 +3927,40 @@ int bus_exec_context_set_transient_property(
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (STR_IN_SET(name, "RootImagePolicy", "MountImagePolicy", "ExtensionImagePolicy")) {
|
||||
_cleanup_(image_policy_freep) ImagePolicy *p = NULL;
|
||||
const char *s;
|
||||
|
||||
r = sd_bus_message_read(message, "s", &s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = image_policy_from_string(s, &p);
|
||||
if (r < 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to parse image policy string: %s", s);
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
_cleanup_free_ char *t = NULL;
|
||||
ImagePolicy **pp =
|
||||
streq(name, "RootImagePolicy") ? &c->root_image_policy :
|
||||
streq(name, "MountImagePolicy") ? &c->mount_image_policy :
|
||||
&c->extension_image_policy;
|
||||
|
||||
r = image_policy_to_string(p, /* simplify= */ true, &t);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
image_policy_free(*pp);
|
||||
*pp = TAKE_PTR(p);
|
||||
|
||||
unit_write_settingf(
|
||||
u, flags, name,
|
||||
"%s=%s",
|
||||
name,
|
||||
t); /* no escaping necessary */
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
+16
-8
@@ -197,15 +197,23 @@ static int bus_service_method_mount(sd_bus_message *message, void *userdata, sd_
|
||||
|
||||
propagate_directory = strjoina("/run/systemd/propagate/", u->id);
|
||||
if (is_image)
|
||||
r = mount_image_in_namespace(unit_pid,
|
||||
propagate_directory,
|
||||
"/run/systemd/incoming/",
|
||||
src, dest, read_only, make_file_or_directory, options);
|
||||
r = mount_image_in_namespace(
|
||||
unit_pid,
|
||||
propagate_directory,
|
||||
"/run/systemd/incoming/",
|
||||
src, dest,
|
||||
read_only,
|
||||
make_file_or_directory,
|
||||
options,
|
||||
c->mount_image_policy ?: &image_policy_service);
|
||||
else
|
||||
r = bind_mount_in_namespace(unit_pid,
|
||||
propagate_directory,
|
||||
"/run/systemd/incoming/",
|
||||
src, dest, read_only, make_file_or_directory);
|
||||
r = bind_mount_in_namespace(
|
||||
unit_pid,
|
||||
propagate_directory,
|
||||
"/run/systemd/incoming/",
|
||||
src, dest,
|
||||
read_only,
|
||||
make_file_or_directory);
|
||||
if (r < 0)
|
||||
return sd_bus_error_set_errnof(error, r, "Failed to mount %s on %s in unit's namespace: %m", src, dest);
|
||||
|
||||
|
||||
+41
-30
@@ -3823,36 +3823,43 @@ static int apply_mount_namespace(
|
||||
goto finalize;
|
||||
}
|
||||
|
||||
r = setup_namespace(root_dir, root_image, context->root_image_options,
|
||||
&ns_info, read_write_paths,
|
||||
needs_sandboxing ? context->read_only_paths : NULL,
|
||||
needs_sandboxing ? context->inaccessible_paths : NULL,
|
||||
needs_sandboxing ? context->exec_paths : NULL,
|
||||
needs_sandboxing ? context->no_exec_paths : NULL,
|
||||
empty_directories,
|
||||
symlinks,
|
||||
bind_mounts,
|
||||
n_bind_mounts,
|
||||
context->temporary_filesystems,
|
||||
context->n_temporary_filesystems,
|
||||
context->mount_images,
|
||||
context->n_mount_images,
|
||||
tmp_dir,
|
||||
var_tmp_dir,
|
||||
creds_path,
|
||||
context->log_namespace,
|
||||
context->mount_propagation_flag,
|
||||
context->root_hash, context->root_hash_size, context->root_hash_path,
|
||||
context->root_hash_sig, context->root_hash_sig_size, context->root_hash_sig_path,
|
||||
context->root_verity,
|
||||
context->extension_images,
|
||||
context->n_extension_images,
|
||||
context->extension_directories,
|
||||
propagate_dir,
|
||||
incoming_dir,
|
||||
extension_dir,
|
||||
root_dir || root_image ? params->notify_socket : NULL,
|
||||
error_path);
|
||||
r = setup_namespace(
|
||||
root_dir,
|
||||
root_image,
|
||||
context->root_image_options,
|
||||
context->root_image_policy ?: &image_policy_service,
|
||||
&ns_info,
|
||||
read_write_paths,
|
||||
needs_sandboxing ? context->read_only_paths : NULL,
|
||||
needs_sandboxing ? context->inaccessible_paths : NULL,
|
||||
needs_sandboxing ? context->exec_paths : NULL,
|
||||
needs_sandboxing ? context->no_exec_paths : NULL,
|
||||
empty_directories,
|
||||
symlinks,
|
||||
bind_mounts,
|
||||
n_bind_mounts,
|
||||
context->temporary_filesystems,
|
||||
context->n_temporary_filesystems,
|
||||
context->mount_images,
|
||||
context->n_mount_images,
|
||||
context->mount_image_policy ?: &image_policy_service,
|
||||
tmp_dir,
|
||||
var_tmp_dir,
|
||||
creds_path,
|
||||
context->log_namespace,
|
||||
context->mount_propagation_flag,
|
||||
context->root_hash, context->root_hash_size, context->root_hash_path,
|
||||
context->root_hash_sig, context->root_hash_sig_size, context->root_hash_sig_path,
|
||||
context->root_verity,
|
||||
context->extension_images,
|
||||
context->n_extension_images,
|
||||
context->extension_image_policy ?: &image_policy_sysext,
|
||||
context->extension_directories,
|
||||
propagate_dir,
|
||||
incoming_dir,
|
||||
extension_dir,
|
||||
root_dir || root_image ? params->notify_socket : NULL,
|
||||
error_path);
|
||||
|
||||
/* If we couldn't set up the namespace this is probably due to a missing capability. setup_namespace() reports
|
||||
* that with a special, recognizable error ENOANO. In this case, silently proceed, but only if exclusively
|
||||
@@ -5789,6 +5796,10 @@ void exec_context_done(ExecContext *c) {
|
||||
|
||||
c->load_credentials = hashmap_free(c->load_credentials);
|
||||
c->set_credentials = hashmap_free(c->set_credentials);
|
||||
|
||||
c->root_image_policy = image_policy_free(c->root_image_policy);
|
||||
c->mount_image_policy = image_policy_free(c->mount_image_policy);
|
||||
c->extension_image_policy = image_policy_free(c->extension_image_policy);
|
||||
}
|
||||
|
||||
int exec_context_destroy_runtime_directory(const ExecContext *c, const char *runtime_prefix) {
|
||||
|
||||
@@ -359,6 +359,8 @@ struct ExecContext {
|
||||
|
||||
Hashmap *set_credentials; /* output id → ExecSetCredential */
|
||||
Hashmap *load_credentials; /* output id → ExecLoadCredential */
|
||||
|
||||
ImagePolicy *root_image_policy, *mount_image_policy, *extension_image_policy;
|
||||
};
|
||||
|
||||
static inline bool exec_context_restrict_namespaces_set(const ExecContext *c) {
|
||||
|
||||
@@ -6,12 +6,15 @@
|
||||
{{type}}.RootDirectory, config_parse_unit_path_printf, true, offsetof({{type}}, exec_context.root_directory)
|
||||
{{type}}.RootImage, config_parse_unit_path_printf, true, offsetof({{type}}, exec_context.root_image)
|
||||
{{type}}.RootImageOptions, config_parse_root_image_options, 0, offsetof({{type}}, exec_context)
|
||||
{{type}}.RootImagePolicy, config_parse_image_policy, 0, offsetof({{type}}, exec_context.root_image_policy)
|
||||
{{type}}.RootHash, config_parse_exec_root_hash, 0, offsetof({{type}}, exec_context)
|
||||
{{type}}.RootHashSignature, config_parse_exec_root_hash_sig, 0, offsetof({{type}}, exec_context)
|
||||
{{type}}.RootVerity, config_parse_unit_path_printf, true, offsetof({{type}}, exec_context.root_verity)
|
||||
{{type}}.ExtensionDirectories, config_parse_namespace_path_strv, 0, offsetof({{type}}, exec_context.extension_directories)
|
||||
{{type}}.ExtensionImages, config_parse_extension_images, 0, offsetof({{type}}, exec_context)
|
||||
{{type}}.ExtensionImagePolicy, config_parse_image_policy, 0, offsetof({{type}}, exec_context.extension_image_policy)
|
||||
{{type}}.MountImages, config_parse_mount_images, 0, offsetof({{type}}, exec_context)
|
||||
{{type}}.MountImagePolicy, config_parse_image_policy, 0, offsetof({{type}}, exec_context.mount_image_policy)
|
||||
{{type}}.User, config_parse_user_group_compat, 0, offsetof({{type}}, exec_context.user)
|
||||
{{type}}.Group, config_parse_user_group_compat, 0, offsetof({{type}}, exec_context.group)
|
||||
{{type}}.SupplementaryGroups, config_parse_user_group_strv_compat, 0, offsetof({{type}}, exec_context.supplementary_groups)
|
||||
|
||||
@@ -1705,6 +1705,45 @@ int config_parse_root_image_options(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_image_policy(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_(image_policy_freep) ImagePolicy *np = NULL;
|
||||
ImagePolicy **p = ASSERT_PTR(data);
|
||||
int r;
|
||||
|
||||
assert(rvalue);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
*p = image_policy_free(*p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = image_policy_from_string(rvalue, &np);
|
||||
if (r == -ENOTUNIQ)
|
||||
return log_syntax(unit, LOG_ERR, filename, line, r, "Duplicate rule in image policy, refusing: %s", rvalue);
|
||||
if (r == -EBADSLT)
|
||||
return log_syntax(unit, LOG_ERR, filename, line, r, "Unknown partition type in image policy, refusing: %s", rvalue);
|
||||
if (r == -EBADRQC)
|
||||
return log_syntax(unit, LOG_ERR, filename, line, r, "Unknown partition policy flag in image policy, refusing: %s", rvalue);
|
||||
if (r < 0)
|
||||
return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse image policy, refusing: %s", rvalue);
|
||||
|
||||
image_policy_free(*p);
|
||||
*p = TAKE_PTR(np);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_exec_root_hash(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
|
||||
@@ -52,6 +52,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_affinity);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_exec_mount_apivfs);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_exec_secure_bits);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_root_image_options);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_image_policy);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_exec_root_hash);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_exec_root_hash_sig);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_capability_set);
|
||||
|
||||
+27
-9
@@ -1240,7 +1240,10 @@ static int mount_mqueuefs(const MountEntry *m) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mount_image(const MountEntry *m, const char *root_directory) {
|
||||
static int mount_image(
|
||||
const MountEntry *m,
|
||||
const char *root_directory,
|
||||
const ImagePolicy *image_policy) {
|
||||
|
||||
_cleanup_free_ char *host_os_release_id = NULL, *host_os_release_version_id = NULL,
|
||||
*host_os_release_sysext_level = NULL;
|
||||
@@ -1262,8 +1265,15 @@ static int mount_image(const MountEntry *m, const char *root_directory) {
|
||||
}
|
||||
|
||||
r = verity_dissect_and_mount(
|
||||
/* src_fd= */ -1, mount_entry_source(m), mount_entry_path(m), m->image_options,
|
||||
host_os_release_id, host_os_release_version_id, host_os_release_sysext_level, NULL);
|
||||
/* src_fd= */ -1,
|
||||
mount_entry_source(m),
|
||||
mount_entry_path(m),
|
||||
m->image_options,
|
||||
image_policy,
|
||||
host_os_release_id,
|
||||
host_os_release_version_id,
|
||||
host_os_release_sysext_level,
|
||||
NULL);
|
||||
if (r == -ENOENT && m->ignore)
|
||||
return 0;
|
||||
if (r == -ESTALE && host_os_release_id)
|
||||
@@ -1336,6 +1346,8 @@ static int follow_symlink(
|
||||
static int apply_one_mount(
|
||||
const char *root_directory,
|
||||
MountEntry *m,
|
||||
const ImagePolicy *mount_image_policy,
|
||||
const ImagePolicy *extension_image_policy,
|
||||
const NamespaceInfo *ns_info) {
|
||||
|
||||
_cleanup_free_ char *inaccessible = NULL;
|
||||
@@ -1505,10 +1517,10 @@ static int apply_one_mount(
|
||||
return mount_mqueuefs(m);
|
||||
|
||||
case MOUNT_IMAGES:
|
||||
return mount_image(m, NULL);
|
||||
return mount_image(m, NULL, mount_image_policy);
|
||||
|
||||
case EXTENSION_IMAGES:
|
||||
return mount_image(m, root_directory);
|
||||
return mount_image(m, root_directory, extension_image_policy);
|
||||
|
||||
case OVERLAY_MOUNT:
|
||||
return mount_overlay(m);
|
||||
@@ -1778,6 +1790,8 @@ static int create_symlinks_from_tuples(const char *root, char **strv_symlinks) {
|
||||
|
||||
static int apply_mounts(
|
||||
const char *root,
|
||||
const ImagePolicy *mount_image_policy,
|
||||
const ImagePolicy *extension_image_policy,
|
||||
const NamespaceInfo *ns_info,
|
||||
MountEntry *mounts,
|
||||
size_t *n_mounts,
|
||||
@@ -1832,7 +1846,7 @@ static int apply_mounts(
|
||||
break;
|
||||
}
|
||||
|
||||
r = apply_one_mount(root, m, ns_info);
|
||||
r = apply_one_mount(root, m, mount_image_policy, extension_image_policy, ns_info);
|
||||
if (r < 0) {
|
||||
if (error_path && mount_entry_path(m))
|
||||
*error_path = strdup(mount_entry_path(m));
|
||||
@@ -2011,7 +2025,8 @@ static int verity_settings_prepare(
|
||||
int setup_namespace(
|
||||
const char* root_directory,
|
||||
const char* root_image,
|
||||
const MountOptions *root_image_options,
|
||||
const MountOptions *root_image_mount_options,
|
||||
const ImagePolicy *root_image_policy,
|
||||
const NamespaceInfo *ns_info,
|
||||
char** read_write_paths,
|
||||
char** read_only_paths,
|
||||
@@ -2026,6 +2041,7 @@ int setup_namespace(
|
||||
size_t n_temporary_filesystems,
|
||||
const MountImage *mount_images,
|
||||
size_t n_mount_images,
|
||||
const ImagePolicy *mount_image_policy,
|
||||
const char* tmp_dir,
|
||||
const char* var_tmp_dir,
|
||||
const char *creds_path,
|
||||
@@ -2040,6 +2056,7 @@ int setup_namespace(
|
||||
const char *verity_data_path,
|
||||
const MountImage *extension_images,
|
||||
size_t n_extension_images,
|
||||
const ImagePolicy *extension_image_policy,
|
||||
char **extension_directories,
|
||||
const char *propagate_dir,
|
||||
const char *incoming_dir,
|
||||
@@ -2113,7 +2130,8 @@ int setup_namespace(
|
||||
r = dissect_loop_device(
|
||||
loop_device,
|
||||
&verity,
|
||||
root_image_options,
|
||||
root_image_mount_options,
|
||||
root_image_policy,
|
||||
dissect_image_flags,
|
||||
&dissected_image);
|
||||
if (r < 0)
|
||||
@@ -2501,7 +2519,7 @@ int setup_namespace(
|
||||
(void) base_filesystem_create(root, UID_INVALID, GID_INVALID);
|
||||
|
||||
/* Now make the magic happen */
|
||||
r = apply_mounts(root, ns_info, mounts, &n_mounts, exec_dir_symlinks, error_path);
|
||||
r = apply_mounts(root, mount_image_policy, extension_image_policy, ns_info, mounts, &n_mounts, exec_dir_symlinks, error_path);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@ int setup_namespace(
|
||||
const char *root_directory,
|
||||
const char *root_image,
|
||||
const MountOptions *root_image_options,
|
||||
const ImagePolicy *root_image_policy,
|
||||
const NamespaceInfo *ns_info,
|
||||
char **read_write_paths,
|
||||
char **read_only_paths,
|
||||
@@ -117,6 +118,7 @@ int setup_namespace(
|
||||
size_t n_temporary_filesystems,
|
||||
const MountImage *mount_images,
|
||||
size_t n_mount_images,
|
||||
const ImagePolicy *mount_image_policy,
|
||||
const char *tmp_dir,
|
||||
const char *var_tmp_dir,
|
||||
const char *creds_path,
|
||||
@@ -131,6 +133,7 @@ int setup_namespace(
|
||||
const char *root_verity,
|
||||
const MountImage *extension_images,
|
||||
size_t n_extension_images,
|
||||
const ImagePolicy *extension_image_policy,
|
||||
char **extension_directories,
|
||||
const char *propagate_dir,
|
||||
const char *incoming_dir,
|
||||
|
||||
Reference in New Issue
Block a user