tree-wide: hook up image dissection policy logic everywhere

This commit is contained in:
Lennart Poettering
2023-04-05 20:45:30 +02:00
parent d452335aa4
commit 84be0c710d
42 changed files with 691 additions and 143 deletions
+61
View File
@@ -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
View File
@@ -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
View File
@@ -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) {
+2
View File
@@ -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) {
+3
View File
@@ -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)
+39
View File
@@ -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,
+1
View File
@@ -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
View File
@@ -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;
+3
View File
@@ -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,