diff options
Diffstat (limited to 'src/portable')
-rw-r--r-- | src/portable/portable.c | 213 | ||||
-rw-r--r-- | src/portable/portable.h | 3 | ||||
-rw-r--r-- | src/portable/portablectl.c | 77 | ||||
-rw-r--r-- | src/portable/portabled-bus.c | 10 | ||||
-rw-r--r-- | src/portable/portabled-image-bus.c | 19 | ||||
-rw-r--r-- | src/portable/portabled.c | 29 | ||||
-rw-r--r-- | src/portable/profile/default/service.conf | 2 | ||||
-rw-r--r-- | src/portable/profile/trusted/service.conf | 2 |
8 files changed, 241 insertions, 114 deletions
diff --git a/src/portable/portable.c b/src/portable/portable.c index 3b2a379..53418c4 100644 --- a/src/portable/portable.c +++ b/src/portable/portable.c @@ -33,6 +33,7 @@ #include "path-lookup.h" #include "portable.h" #include "process-util.h" +#include "rm-rf.h" #include "selinux-util.h" #include "set.h" #include "signal-util.h" @@ -42,6 +43,7 @@ #include "strv.h" #include "tmpfile-util.h" #include "user-util.h" +#include "vpick.h" /* Markers used in the first line of our 20-portable.conf unit file drop-in to determine, that a) the unit file was * dropped there by the portable service logic and b) for which image it was dropped there. */ @@ -181,7 +183,7 @@ static int extract_now( _cleanup_hashmap_free_ Hashmap *unit_files = NULL; _cleanup_(portable_metadata_unrefp) PortableMetadata *os_release = NULL; - _cleanup_(lookup_paths_free) LookupPaths paths = {}; + _cleanup_(lookup_paths_done) LookupPaths paths = {}; _cleanup_close_ int os_release_fd = -EBADF; _cleanup_free_ char *os_release_path = NULL; const char *os_release_id; @@ -361,7 +363,13 @@ static int portable_extract_by_path( assert(path); - r = loop_device_make_by_path(path, O_RDONLY, /* sector_size= */ UINT32_MAX, LO_FLAGS_PARTSCAN, LOCK_SH, &d); + r = loop_device_make_by_path( + path, + O_RDONLY, + /* sector_size= */ UINT32_MAX, + LO_FLAGS_PARTSCAN, + LOCK_SH, + &d); if (r == -EISDIR) { _cleanup_free_ char *image_name = NULL; @@ -383,6 +391,21 @@ static int portable_extract_by_path( _cleanup_(rmdir_and_freep) char *tmpdir = NULL; _cleanup_close_pair_ int seq[2] = EBADF_PAIR; _cleanup_(sigkill_waitp) pid_t child = 0; + DissectImageFlags flags = + DISSECT_IMAGE_READ_ONLY | + DISSECT_IMAGE_GENERIC_ROOT | + DISSECT_IMAGE_REQUIRE_ROOT | + DISSECT_IMAGE_DISCARD_ON_LOOP | + DISSECT_IMAGE_RELAX_VAR_CHECK | + DISSECT_IMAGE_USR_NO_ROOT | + DISSECT_IMAGE_ADD_PARTITION_DEVICES | + DISSECT_IMAGE_PIN_PARTITION_DEVICES | + DISSECT_IMAGE_ALLOW_USERSPACE_VERITY; + + if (path_is_extension) + flags |= DISSECT_IMAGE_VALIDATE_OS_EXT | (relax_extension_release_check ? DISSECT_IMAGE_RELAX_EXTENSION_CHECK : 0); + else + flags |= DISSECT_IMAGE_VALIDATE_OS; /* We now have a loopback block device, let's fork off a child in its own mount namespace, mount it * there, and extract the metadata we need. The metadata is sent from the child back to us. */ @@ -398,14 +421,7 @@ static int portable_extract_by_path( /* verity= */ NULL, /* mount_options= */ NULL, image_policy, - DISSECT_IMAGE_READ_ONLY | - DISSECT_IMAGE_GENERIC_ROOT | - DISSECT_IMAGE_REQUIRE_ROOT | - DISSECT_IMAGE_DISCARD_ON_LOOP | - DISSECT_IMAGE_RELAX_VAR_CHECK | - DISSECT_IMAGE_USR_NO_ROOT | - DISSECT_IMAGE_ADD_PARTITION_DEVICES | - DISSECT_IMAGE_PIN_PARTITION_DEVICES, + flags, &m); if (r == -ENOPKG) sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Couldn't identify a suitable partition table or file system in '%s'.", path); @@ -427,15 +443,8 @@ static int portable_extract_by_path( if (r < 0) return r; if (r == 0) { - DissectImageFlags flags = DISSECT_IMAGE_READ_ONLY; - seq[0] = safe_close(seq[0]); - if (path_is_extension) - flags |= DISSECT_IMAGE_VALIDATE_OS_EXT | (relax_extension_release_check ? DISSECT_IMAGE_RELAX_EXTENSION_CHECK : 0); - else - flags |= DISSECT_IMAGE_VALIDATE_OS; - r = dissected_image_mount( m, tmpdir, @@ -556,6 +565,7 @@ static int extract_image_and_extensions( _cleanup_free_ char *id = NULL, *version_id = NULL, *sysext_level = NULL, *confext_level = NULL; _cleanup_(portable_metadata_unrefp) PortableMetadata *os_release = NULL; _cleanup_ordered_hashmap_free_ OrderedHashmap *extension_images = NULL, *extension_releases = NULL; + _cleanup_(pick_result_done) PickResult result = PICK_RESULT_NULL; _cleanup_hashmap_free_ Hashmap *unit_files = NULL; _cleanup_strv_free_ char **valid_prefixes = NULL; _cleanup_(image_unrefp) Image *image = NULL; @@ -564,7 +574,27 @@ static int extract_image_and_extensions( assert(name_or_path); - r = image_find_harder(IMAGE_PORTABLE, name_or_path, NULL, &image); + /* If we get a path, then check if it can be resolved with vpick. We need this as we might just + * get a simple image name, which would make vpick error out. */ + if (path_is_absolute(name_or_path)) { + r = path_pick(/* toplevel_path= */ NULL, + /* toplevel_fd= */ AT_FDCWD, + name_or_path, + &pick_filter_image_any, + PICK_ARCHITECTURE|PICK_TRIES|PICK_RESOLVE, + &result); + if (r < 0) + return r; + if (!result.path) + return log_debug_errno( + SYNTHETIC_ERRNO(ENOENT), + "No matching entry in .v/ directory %s found.", + name_or_path); + + name_or_path = result.path; + } + + r = image_find_harder(IMAGE_PORTABLE, name_or_path, /* root= */ NULL, &image); if (r < 0) return r; @@ -580,9 +610,29 @@ static int extract_image_and_extensions( } STRV_FOREACH(p, extension_image_paths) { + _cleanup_(pick_result_done) PickResult ext_result = PICK_RESULT_NULL; _cleanup_(image_unrefp) Image *new = NULL; + const char *path = *p; + + if (path_is_absolute(*p)) { + r = path_pick(/* toplevel_path= */ NULL, + /* toplevel_fd= */ AT_FDCWD, + *p, + &pick_filter_image_any, + PICK_ARCHITECTURE|PICK_TRIES|PICK_RESOLVE, + &ext_result); + if (r < 0) + return r; + if (!ext_result.path) + return log_debug_errno( + SYNTHETIC_ERRNO(ENOENT), + "No matching entry in .v/ directory %s found.", + *p); - r = image_find_harder(IMAGE_PORTABLE, *p, NULL, &new); + path = ext_result.path; + } + + r = image_find_harder(IMAGE_PORTABLE, path, NULL, &new); if (r < 0) return r; @@ -1341,7 +1391,7 @@ static int attach_unit_file( return 0; } -static int image_symlink( +static int image_target_path( const char *image_path, PortableFlags flags, char **ret) { @@ -1367,37 +1417,66 @@ static int image_symlink( return 0; } -static int install_image_symlink( +static int install_image( const char *image_path, PortableFlags flags, PortableChange **changes, size_t *n_changes) { - _cleanup_free_ char *sl = NULL; + _cleanup_free_ char *target = NULL; int r; assert(image_path); - /* If the image is outside of the image search also link it into it, so that it can be found with short image - * names and is listed among the images. */ + /* If the image is outside of the image search also link it into it, so that it can be found with + * short image names and is listed among the images. If we are operating in mixed mode, the image is + * copied instead. */ if (image_in_search_path(IMAGE_PORTABLE, NULL, image_path)) return 0; - r = image_symlink(image_path, flags, &sl); + r = image_target_path(image_path, flags, &target); if (r < 0) return log_debug_errno(r, "Failed to generate image symlink path: %m"); - (void) mkdir_parents(sl, 0755); + (void) mkdir_parents(target, 0755); + + if (flags & PORTABLE_MIXED_COPY_LINK) { + r = copy_tree(image_path, + target, + UID_INVALID, + GID_INVALID, + COPY_REFLINK | COPY_FSYNC | COPY_FSYNC_FULL | COPY_SYNCFS, + /* denylist= */ NULL, + /* subvolumes= */ NULL); + if (r < 0) + return log_debug_errno( + r, + "Failed to copy %s %s %s: %m", + image_path, + special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), + target); - if (symlink(image_path, sl) < 0) - return log_debug_errno(errno, "Failed to link %s %s %s: %m", image_path, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), sl); + } else { + if (symlink(image_path, target) < 0) + return log_debug_errno( + errno, + "Failed to link %s %s %s: %m", + image_path, + special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), + target); + } - (void) portable_changes_add(changes, n_changes, PORTABLE_SYMLINK, sl, image_path); + (void) portable_changes_add( + changes, + n_changes, + (flags & PORTABLE_MIXED_COPY_LINK) ? PORTABLE_COPY : PORTABLE_SYMLINK, + target, + image_path); return 0; } -static int install_image_and_extensions_symlinks( +static int install_image_and_extensions( const Image *image, OrderedHashmap *extension_images, PortableFlags flags, @@ -1410,12 +1489,12 @@ static int install_image_and_extensions_symlinks( assert(image); ORDERED_HASHMAP_FOREACH(ext, extension_images) { - r = install_image_symlink(ext->path, flags, changes, n_changes); + r = install_image(ext->path, flags, changes, n_changes); if (r < 0) return r; } - r = install_image_symlink(image->path, flags, changes, n_changes); + r = install_image(image->path, flags, changes, n_changes); if (r < 0) return r; @@ -1436,6 +1515,7 @@ static void log_portable_verb( const char *verb, const char *message_id, const char *image_path, + const char *profile, OrderedHashmap *extension_images, char **extension_image_paths, PortableFlags flags) { @@ -1494,12 +1574,14 @@ static void log_portable_verb( LOG_CONTEXT_PUSH_STRV(extension_base_names); log_struct(LOG_INFO, - LOG_MESSAGE("Successfully %s%s '%s%s%s'", + LOG_MESSAGE("Successfully %s%s '%s%s%s%s%s'", verb, FLAGS_SET(flags, PORTABLE_RUNTIME) ? " ephemeral" : "", image_path, isempty(extensions_joined) ? "" : "' and its extension(s) '", - strempty(extensions_joined)), + strempty(extensions_joined), + isempty(profile) ? "" : "' using profile '", + strempty(profile)), message_id, "PORTABLE_ROOT=%s", strna(root_base_name)); } @@ -1519,7 +1601,7 @@ int portable_attach( _cleanup_ordered_hashmap_free_ OrderedHashmap *extension_images = NULL, *extension_releases = NULL; _cleanup_(portable_metadata_unrefp) PortableMetadata *os_release = NULL; _cleanup_hashmap_free_ Hashmap *unit_files = NULL; - _cleanup_(lookup_paths_free) LookupPaths paths = {}; + _cleanup_(lookup_paths_done) LookupPaths paths = {}; _cleanup_strv_free_ char **valid_prefixes = NULL; _cleanup_(image_unrefp) Image *image = NULL; PortableMetadata *item; @@ -1608,14 +1690,15 @@ int portable_attach( return sd_bus_error_set_errnof(error, r, "Failed to attach unit '%s': %m", item->name); } - /* We don't care too much for the image symlink, it's just a convenience thing, it's not necessary for proper - * operation otherwise. */ - (void) install_image_and_extensions_symlinks(image, extension_images, flags, changes, n_changes); + /* We don't care too much for the image symlink/copy, it's just a convenience thing, it's not necessary for + * proper operation otherwise. */ + (void) install_image_and_extensions(image, extension_images, flags, changes, n_changes); log_portable_verb( "attached", "MESSAGE_ID=" SD_MESSAGE_PORTABLE_ATTACHED_STR, image->path, + profile, extension_images, /* extension_image_paths= */ NULL, flags); @@ -1650,6 +1733,7 @@ static bool marker_matches_images(const char *marker, const char *name_or_path, while (!isempty(marker)) STRV_FOREACH(image_name_or_path, root_and_extensions) { _cleanup_free_ char *image = NULL, *base_image = NULL, *base_image_name_or_path = NULL; + _cleanup_(pick_result_done) PickResult result = PICK_RESULT_NULL; r = extract_first_word(&marker, &image, ":", EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE); if (r < 0) @@ -1661,9 +1745,23 @@ static bool marker_matches_images(const char *marker, const char *name_or_path, if (r < 0) return log_debug_errno(r, "Failed to extract image name from %s, ignoring: %m", image); - r = path_extract_image_name(*image_name_or_path, &base_image_name_or_path); + r = path_pick(/* toplevel_path= */ NULL, + /* toplevel_fd= */ AT_FDCWD, + *image_name_or_path, + &pick_filter_image_any, + PICK_ARCHITECTURE|PICK_TRIES|PICK_RESOLVE, + &result); + if (r < 0) + return r; + if (!result.path) + return log_debug_errno( + SYNTHETIC_ERRNO(ENOENT), + "No matching entry in .v/ directory %s found.", + *image_name_or_path); + + r = path_extract_image_name(result.path, &base_image_name_or_path); if (r < 0) - return log_debug_errno(r, "Failed to extract image name from %s, ignoring: %m", *image_name_or_path); + return log_debug_errno(r, "Failed to extract image name from %s, ignoring: %m", result.path); if (!streq(base_image, base_image_name_or_path)) { if (match_all) @@ -1746,7 +1844,7 @@ int portable_detach( size_t *n_changes, sd_bus_error *error) { - _cleanup_(lookup_paths_free) LookupPaths paths = {}; + _cleanup_(lookup_paths_done) LookupPaths paths = {}; _cleanup_set_free_ Set *unit_files = NULL, *markers = NULL; _cleanup_free_ char *extensions = NULL; _cleanup_closedir_ DIR *d = NULL; @@ -1875,34 +1973,24 @@ int portable_detach( portable_changes_add_with_prefix(changes, n_changes, PORTABLE_UNLINK, where, md, NULL); } - /* Now, also drop any image symlink, for images outside of the sarch path */ + /* Now, also drop any image symlink or copy, for images outside of the sarch path */ SET_FOREACH(item, markers) { - _cleanup_free_ char *sl = NULL; - struct stat st; + _cleanup_free_ char *target = NULL; - r = image_symlink(item, flags, &sl); + r = image_target_path(item, flags, &target); if (r < 0) { - log_debug_errno(r, "Failed to determine image symlink for '%s', ignoring: %m", item); + log_debug_errno(r, "Failed to determine image path for '%s', ignoring: %m", item); continue; } - if (lstat(sl, &st) < 0) { - log_debug_errno(errno, "Failed to stat '%s', ignoring: %m", sl); - continue; - } - - if (!S_ISLNK(st.st_mode)) { - log_debug("Image '%s' is not a symlink, ignoring.", sl); - continue; - } - - if (unlink(sl) < 0) { - log_debug_errno(errno, "Can't remove image symlink '%s': %m", sl); + r = rm_rf(target, REMOVE_ROOT | REMOVE_PHYSICAL | REMOVE_MISSING_OK | REMOVE_SYNCFS); + if (r < 0) { + log_debug_errno(r, "Can't remove image '%s': %m", target); - if (errno != ENOENT && ret >= 0) - ret = -errno; + if (r != -ENOENT) + RET_GATHER(ret, r); } else - portable_changes_add(changes, n_changes, PORTABLE_UNLINK, sl, NULL); + portable_changes_add(changes, n_changes, PORTABLE_UNLINK, target, NULL); } /* Try to remove the unit file directory, if we can */ @@ -1913,6 +2001,7 @@ int portable_detach( "detached", "MESSAGE_ID=" SD_MESSAGE_PORTABLE_DETACHED_STR, name_or_path, + /* profile= */ NULL, /* extension_images= */ NULL, extension_image_paths, flags); @@ -1941,7 +2030,7 @@ static int portable_get_state_internal( PortableState *ret, sd_bus_error *error) { - _cleanup_(lookup_paths_free) LookupPaths paths = {}; + _cleanup_(lookup_paths_done) LookupPaths paths = {}; bool found_enabled = false, found_running = false; _cleanup_set_free_ Set *unit_files = NULL; _cleanup_closedir_ DIR *d = NULL; diff --git a/src/portable/portable.h b/src/portable/portable.h index c4a9d51..f5bb190 100644 --- a/src/portable/portable.h +++ b/src/portable/portable.h @@ -27,7 +27,8 @@ typedef enum PortableFlags { PORTABLE_FORCE_EXTENSION = 1 << 2, /* Public API via DBUS, do not change */ PORTABLE_PREFER_COPY = 1 << 3, PORTABLE_PREFER_SYMLINK = 1 << 4, - PORTABLE_REATTACH = 1 << 5, + PORTABLE_MIXED_COPY_LINK = 1 << 5, + PORTABLE_REATTACH = 1 << 6, _PORTABLE_MASK_PUBLIC = PORTABLE_RUNTIME | PORTABLE_FORCE_ATTACH | PORTABLE_FORCE_EXTENSION, _PORTABLE_TYPE_MAX, _PORTABLE_TYPE_INVALID = -EINVAL, diff --git a/src/portable/portablectl.c b/src/portable/portablectl.c index 1588b17..57b930d 100644 --- a/src/portable/portablectl.c +++ b/src/portable/portablectl.c @@ -50,6 +50,7 @@ static bool arg_now = false; static bool arg_no_block = false; static char **arg_extension_images = NULL; static bool arg_force = false; +static bool arg_clean = false; STATIC_DESTRUCTOR_REGISTER(arg_extension_images, strv_freep); @@ -769,13 +770,49 @@ static int maybe_stop_enable_restart(sd_bus *bus, sd_bus_message *reply) { return 0; } -static int maybe_stop_disable(sd_bus *bus, char *image, char *argv[]) { +static int maybe_clean_units(sd_bus *bus, char **units) { + int r; + + assert(bus); + + if (!arg_clean) + return 0; + + STRV_FOREACH(name, units) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + + r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "CleanUnit"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(m, "s", *name); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append_strv(m, STRV_MAKE("all", "fdstore")); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_call(bus, m, 0, &error, NULL); + if (r < 0) + return log_error_errno( + r, + "Failed to call CleanUnit on portable service %s: %s", + *name, + bus_error_message(&error, r)); + } + + return 0; +} + +static int maybe_stop_disable_clean(sd_bus *bus, char *image, char *argv[]) { _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *wait = NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - _cleanup_strv_free_ char **matches = NULL; + _cleanup_strv_free_ char **matches = NULL, **units = NULL; int r; - if (!arg_enable && !arg_now) + if (!arg_enable && !arg_now && !arg_clean) return 0; r = determine_matches(argv[1], argv + 2, true, &matches); @@ -829,6 +866,10 @@ static int maybe_stop_disable(sd_bus *bus, char *image, char *argv[]) { (void) maybe_start_stop_restart(bus, name, "StopUnit", wait); (void) maybe_enable_disable(bus, name, false); + + r = strv_extend(&units, name); + if (r < 0) + return log_oom(); } r = sd_bus_message_exit_container(reply); @@ -840,6 +881,9 @@ static int maybe_stop_disable(sd_bus *bus, char *image, char *argv[]) { if (r < 0) return r; + /* Need to ensure all units are stopped before calling CleanUnit, as files might be in use. */ + (void) maybe_clean_units(bus, units); + return 0; } @@ -942,7 +986,7 @@ static int detach_image(int argc, char *argv[], void *userdata) { (void) polkit_agent_open_if_enabled(arg_transport, arg_ask_password); - (void) maybe_stop_disable(bus, image, argv); + (void) maybe_stop_disable_clean(bus, image, argv); method = strv_isempty(arg_extension_images) && !arg_force ? "DetachImage" : "DetachImageWithExtensions"; @@ -1030,7 +1074,7 @@ static int list_images(int argc, char *argv[], void *userdata) { if (r < 0) return bus_log_parse_error(r); - if (table_get_rows(table) > 1) { + if (!table_isempty(table)) { r = table_set_sort(table, (size_t) 0); if (r < 0) return table_log_sort_error(r); @@ -1043,10 +1087,10 @@ static int list_images(int argc, char *argv[], void *userdata) { } if (arg_legend) { - if (table_get_rows(table) > 1) - printf("\n%zu images listed.\n", table_get_rows(table) - 1); - else + if (table_isempty(table)) printf("No images.\n"); + else + printf("\n%zu images listed.\n", table_get_rows(table) - 1); } return 0; @@ -1251,7 +1295,8 @@ static int help(int argc, char *argv[], void *userdata) { " -M --machine=CONTAINER Operate on local container\n" " -q --quiet Suppress informational messages\n" " -p --profile=PROFILE Pick security profile for portable service\n" - " --copy=copy|auto|symlink Prefer copying or symlinks if possible\n" + " --copy=copy|auto|symlink|mixed\n" + " Pick copying or symlinking of resources\n" " --runtime Attach portable service until next reboot only\n" " --no-reload Don't reload the system and service manager\n" " --cat When inspecting include unit and os-release file\n" @@ -1264,6 +1309,9 @@ static int help(int argc, char *argv[], void *userdata) { " --extension=PATH Extend the image with an overlay\n" " --force Skip 'already active' check when attaching or\n" " detaching an image (with extensions)\n" + " --clean When detaching, also remove configuration, state,\n" + " cache, logs or runtime data of the portable\n" + " service(s)\n" "\nSee the %s for details.\n", program_invocation_short_name, ansi_highlight(), @@ -1290,6 +1338,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_NO_BLOCK, ARG_EXTENSION, ARG_FORCE, + ARG_CLEAN, }; static const struct option options[] = { @@ -1311,6 +1360,7 @@ static int parse_argv(int argc, char *argv[]) { { "no-block", no_argument, NULL, ARG_NO_BLOCK }, { "extension", required_argument, NULL, ARG_EXTENSION }, { "force", no_argument, NULL, ARG_FORCE }, + { "clean", no_argument, NULL, ARG_CLEAN }, {} }; @@ -1372,12 +1422,13 @@ static int parse_argv(int argc, char *argv[]) { case ARG_COPY: if (streq(optarg, "auto")) arg_copy_mode = NULL; - else if (STR_IN_SET(optarg, "copy", "symlink")) + else if (STR_IN_SET(optarg, "copy", "symlink", "mixed")) arg_copy_mode = optarg; else if (streq(optarg, "help")) { puts("auto\n" "copy\n" - "symlink"); + "symlink\n" + "mixed\n"); return 0; } else return log_error_errno(SYNTHETIC_ERRNO(EINVAL), @@ -1419,6 +1470,10 @@ static int parse_argv(int argc, char *argv[]) { arg_force = true; break; + case ARG_CLEAN: + arg_clean = true; + break; + case '?': return -EINVAL; diff --git a/src/portable/portabled-bus.c b/src/portable/portabled-bus.c index 0d55180..4f239e2 100644 --- a/src/portable/portabled-bus.c +++ b/src/portable/portabled-bus.c @@ -320,11 +320,8 @@ static int method_detach_image(sd_bus_message *message, void *userdata, sd_bus_e r = bus_verify_polkit_async( message, - CAP_SYS_ADMIN, "org.freedesktop.portable1.attach-images", - NULL, - false, - UID_INVALID, + /* details= */ NULL, &m->polkit_registry, error); if (r < 0) @@ -377,11 +374,8 @@ static int method_set_pool_limit(sd_bus_message *message, void *userdata, sd_bus r = bus_verify_polkit_async( message, - CAP_SYS_ADMIN, "org.freedesktop.portable1.manage-images", - NULL, - false, - UID_INVALID, + /* details= */ NULL, &m->polkit_registry, error); if (r < 0) diff --git a/src/portable/portabled-image-bus.c b/src/portable/portabled-image-bus.c index 1f61c3b..8db5574 100644 --- a/src/portable/portabled-image-bus.c +++ b/src/portable/portabled-image-bus.c @@ -366,6 +366,8 @@ int bus_image_common_attach( flags |= PORTABLE_PREFER_SYMLINK; else if (streq(copy_mode, "copy")) flags |= PORTABLE_PREFER_COPY; + else if (streq(copy_mode, "mixed")) + flags |= PORTABLE_MIXED_COPY_LINK; else if (!isempty(copy_mode)) return sd_bus_reply_method_errorf(message, SD_BUS_ERROR_INVALID_ARGS, "Unknown copy mode '%s'", copy_mode); @@ -451,11 +453,8 @@ static int bus_image_method_detach( r = bus_verify_polkit_async( message, - CAP_SYS_ADMIN, "org.freedesktop.portable1.attach-images", - NULL, - false, - UID_INVALID, + /* details= */ NULL, &m->polkit_registry, error); if (r < 0) @@ -698,6 +697,8 @@ int bus_image_common_reattach( flags |= PORTABLE_PREFER_SYMLINK; else if (streq(copy_mode, "copy")) flags |= PORTABLE_PREFER_COPY; + else if (streq(copy_mode, "mixed")) + flags |= PORTABLE_MIXED_COPY_LINK; else if (!isempty(copy_mode)) return sd_bus_reply_method_errorf(message, SD_BUS_ERROR_INVALID_ARGS, "Unknown copy mode '%s'", copy_mode); @@ -1010,11 +1011,8 @@ int bus_image_acquire( if (mode == BUS_IMAGE_AUTHENTICATE_ALL) { r = bus_verify_polkit_async( message, - CAP_SYS_ADMIN, polkit_action, - NULL, - false, - UID_INVALID, + /* details= */ NULL, &m->polkit_registry, error); if (r < 0) @@ -1064,11 +1062,8 @@ int bus_image_acquire( if (mode == BUS_IMAGE_AUTHENTICATE_BY_PATH) { r = bus_verify_polkit_async( message, - CAP_SYS_ADMIN, polkit_action, - NULL, - false, - UID_INVALID, + /* details= */ NULL, &m->polkit_registry, error); if (r < 0) diff --git a/src/portable/portabled.c b/src/portable/portabled.c index 136c5fa..d46ac01 100644 --- a/src/portable/portabled.c +++ b/src/portable/portabled.c @@ -65,7 +65,7 @@ static Manager* manager_unref(Manager *m) { sd_event_source_unref(m->image_cache_defer_event); - bus_verify_polkit_async_registry_free(m->polkit_registry); + hashmap_free(m->polkit_registry); sd_bus_flush_close_unref(m->bus); sd_event_unref(m->event); @@ -122,17 +122,6 @@ static bool check_idle(void *userdata) { return !m->operations; } -static int manager_run(Manager *m) { - assert(m); - - return bus_event_loop_with_idle( - m->event, - m->bus, - "org.freedesktop.portable1", - DEFAULT_EXIT_USEC, - check_idle, m); -} - static int run(int argc, char *argv[]) { _cleanup_(manager_unrefp) Manager *m = NULL; int r; @@ -152,7 +141,7 @@ static int run(int argc, char *argv[]) { if (argc != 1) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "This program takes no arguments."); - assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGTERM, SIGINT, SIGRTMIN+18, -1) >= 0); + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGTERM, SIGINT, SIGRTMIN+18) >= 0); r = manager_new(&m); if (r < 0) @@ -162,16 +151,20 @@ static int run(int argc, char *argv[]) { if (r < 0) return log_error_errno(r, "Failed to fully start up daemon: %m"); - log_debug("systemd-portabled running as pid " PID_FMT, getpid_cached()); r = sd_notify(false, NOTIFY_READY); if (r < 0) log_warning_errno(r, "Failed to send readiness notification, ignoring: %m"); - r = manager_run(m); + r = bus_event_loop_with_idle( + m->event, + m->bus, + "org.freedesktop.portable1", + DEFAULT_EXIT_USEC, + check_idle, m); + if (r < 0) + return log_error_errno(r, "Failed to run main loop: %m"); - (void) sd_notify(false, NOTIFY_STOPPING); - log_debug("systemd-portabled stopped as pid " PID_FMT, getpid_cached()); - return r; + return 0; } DEFINE_MAIN_FUNCTION(run); diff --git a/src/portable/profile/default/service.conf b/src/portable/profile/default/service.conf index 230aa60..5c447d6 100644 --- a/src/portable/profile/default/service.conf +++ b/src/portable/profile/default/service.conf @@ -4,7 +4,7 @@ MountAPIVFS=yes BindReadOnlyPaths=/dev/log /run/systemd/journal/socket /run/systemd/journal/stdout BindReadOnlyPaths=/etc/machine-id -BindReadOnlyPaths=/etc/resolv.conf +BindReadOnlyPaths=-/etc/resolv.conf BindReadOnlyPaths=/run/dbus/system_bus_socket DynamicUser=yes RemoveIPC=yes diff --git a/src/portable/profile/trusted/service.conf b/src/portable/profile/trusted/service.conf index 04deeb2..144d4f6 100644 --- a/src/portable/profile/trusted/service.conf +++ b/src/portable/profile/trusted/service.conf @@ -5,4 +5,4 @@ MountAPIVFS=yes PrivateTmp=yes BindPaths=/run BindReadOnlyPaths=/etc/machine-id -BindReadOnlyPaths=/etc/resolv.conf +BindReadOnlyPaths=-/etc/resolv.conf |