diff --git a/src/shared/extension-util.c b/src/shared/extension-util.c index 1f99f46e8d..d993b47de5 100644 --- a/src/shared/extension-util.c +++ b/src/shared/extension-util.c @@ -1,12 +1,20 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include + #include "alloc-util.h" #include "architecture.h" +#include "blockdev-util.h" #include "chase.h" +#include "devnum-util.h" #include "env-util.h" #include "extension-util.h" +#include "fd-util.h" +#include "fileio.h" #include "log.h" #include "os-util.h" +#include "path-util.h" +#include "stat-util.h" #include "string-util.h" #include "strv.h" @@ -178,3 +186,45 @@ int extension_has_forbidden_content(const char *root) { return 0; } + +int extension_overlay_block(const char *p, ImageClass image_class, dev_t *ret) { + int r; + + assert(p); + assert(ret); + + /* Tries to read the backing device information systemd-sysext puts in + * the virtual file .systemd-sysext/.systemd-confext */ + + _cleanup_free_ char *j = path_join(p, image_class == IMAGE_CONFEXT ? ".systemd-confext" : ".systemd-sysext"); + if (!j) + return log_oom_debug(); + + _cleanup_close_ int fd = open(j, O_RDONLY|O_DIRECTORY); + if (fd < 0) + return log_debug_errno(errno, "Failed to open '%s': %m", j); + + r = fd_is_fs_type(fd, OVERLAYFS_SUPER_MAGIC); + if (r < 0) + return log_debug_errno(r, "Failed to determine backing file system of '%s': %m", j); + if (r == 0) + return log_debug_errno( + SYNTHETIC_ERRNO(ENOTTY), "Backing file system of '%s' is not an overlayfs.", j); + + _cleanup_free_ char *buf = NULL; + r = read_one_line_file_at(fd, "backing", &buf); + if (r < 0) + return log_debug_errno(r, "Failed to read contents of '%s/backing': %m", j); + + r = parse_devnum(buf, ret); + if (r < 0) + return log_debug_errno(r, "Failed to parse contents of '%s/backing': %m", j); + + if (major(*ret) == 0) { /* not a block device? */ + *ret = 0; + return 0; + } + + (void) block_get_originating(*ret, ret, /* recursive= */ false); + return 1; +} diff --git a/src/shared/extension-util.h b/src/shared/extension-util.h index 08bdd7f33e..ad8f90f8ca 100644 --- a/src/shared/extension-util.h +++ b/src/shared/extension-util.h @@ -22,3 +22,6 @@ int parse_env_extension_hierarchies(char ***ret_hierarchies, const char *hierarc /* Insist that extension images do not overwrite the underlying OS release file (it's fine if they place one * in /etc/os-release, i.e. where things don't matter, as they aren't merged.) */ int extension_has_forbidden_content(const char *root); + +/* Find the backing device. Returns >0 on success, 0 if the volume is not an extension, and <0 on error. */ +int extension_overlay_block(const char *p, ImageClass image_class, dev_t *ret); diff --git a/src/sysupdate/sysupdate-resource.c b/src/sysupdate/sysupdate-resource.c index cfc0d09ae6..b6cebee314 100644 --- a/src/sysupdate/sysupdate-resource.c +++ b/src/sysupdate/sysupdate-resource.c @@ -1,7 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #include -#include #include #include @@ -10,10 +9,10 @@ #include "build-path.h" #include "chase.h" #include "device-util.h" -#include "devnum-util.h" #include "dirent-util.h" #include "env-util.h" #include "errno-util.h" +#include "extension-util.h" #include "fd-util.h" #include "fdisk-util.h" #include "fileio.h" @@ -23,6 +22,7 @@ #include "hexdecoct.h" #include "import-util.h" #include "iovec-util.h" +#include "os-util.h" #include "path-util.h" #include "pidref.h" #include "process-util.h" @@ -766,47 +766,6 @@ Instance* resource_find_instance(Resource *rr, const char *version) { return *found; } -static int get_sysext_overlay_block(const char *p, dev_t *ret) { - int r; - - assert(p); - assert(ret); - - /* Tries to read the backing device information systemd-sysext puts in the virtual file - * /usr/.systemd-sysext/backing */ - - _cleanup_free_ char *j = path_join(p, ".systemd-sysext"); - if (!j) - return log_oom_debug(); - - _cleanup_close_ int fd = open(j, O_RDONLY|O_DIRECTORY); - if (fd < 0) - return log_debug_errno(errno, "Failed to open '%s': %m", j); - - r = fd_is_fs_type(fd, OVERLAYFS_SUPER_MAGIC); - if (r < 0) - return log_debug_errno(r, "Failed to determine backing file system of '%s': %m", j); - if (r == 0) - return log_debug_errno(SYNTHETIC_ERRNO(ENOTTY), "Backing file system of '%s' is not an overlayfs.", j); - - _cleanup_free_ char *buf = NULL; - r = read_one_line_file_at(fd, "backing", &buf); - if (r < 0) - return log_debug_errno(r, "Failed to read contents of '%s/backing': %m", j); - - r = parse_devnum(buf, ret); - if (r < 0) - return log_debug_errno(r, "Failed to parse contents of '%s/backing': %m", j); - - if (major(*ret) == 0) { /* not a block device? */ - *ret = 0; - return 0; - } - - (void) block_get_originating(*ret, ret, /* recursive= */ false); - return 1; -} - int resource_resolve_path( Resource *rr, const char *root, @@ -858,7 +817,7 @@ int resource_resolve_path( /* volatile-root not found */ r = get_block_device_harder("/usr/", &d); if (r == 0) /* Not backed by a block device? Let's see if this is a sysext overlayfs instance */ - r = get_sysext_overlay_block("/usr/", &d); + r = extension_overlay_block("/usr/", IMAGE_SYSEXT, &d); if (r < 0) return log_error_errno(r, "Failed to determine block device of file system: %m"); } else if (!S_ISBLK(orig_root_stats.st_mode)) /* symlink was present but not block device */