1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-31 14:50:15 +03:00

sysupdate: don't get confused by sysext on /usr/

Fixes: #24562
This commit is contained in:
Lennart Poettering 2025-03-05 14:23:17 +01:00
parent 02d0848df3
commit de4144cfc3

View File

@ -20,6 +20,7 @@
#include "hexdecoct.h"
#include "import-util.h"
#include "macro.h"
#include "missing_magic.h"
#include "process-util.h"
#include "sort-util.h"
#include "string-table.h"
@ -552,6 +553,47 @@ 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);
return 1;
}
int resource_resolve_path(
Resource *rr,
const char *root,
@ -571,8 +613,6 @@ int resource_resolve_path(
path_relative_to_to_string(rr->path_relative_to));
if (rr->path_auto) {
struct stat orig_root_stats;
/* NB: If the root mount has been replaced by some form of volatile file system (overlayfs),
* the original root block device node is symlinked in /run/systemd/volatile-root. Let's
* follow that link here. If that doesn't exist, we check the backing device of "/usr". We
@ -596,12 +636,18 @@ int resource_resolve_path(
return log_error_errno(SYNTHETIC_ERRNO(EPERM),
"Block device is not allowed when using --root= mode.");
r = stat("/run/systemd/volatile-root", &orig_root_stats);
struct stat orig_root_stats;
r = RET_NERRNO(stat("/run/systemd/volatile-root", &orig_root_stats));
if (r < 0) {
if (errno == ENOENT) /* volatile-root not found */
r = get_block_device_harder("/usr/", &d);
else
if (r != -ENOENT)
return log_error_errno(r, "Failed to stat /run/systemd/volatile-root: %m");
/* 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);
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 */
return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK), "/run/systemd/volatile-root is not linked to a block device.");
else /* symlink was present and a block device */
@ -643,7 +689,9 @@ int resource_resolve_path(
if (real_fd < 0)
return log_error_errno(real_fd, "Failed to convert O_PATH file descriptor for %s to regular file descriptor: %m", rr->path);
r = get_block_device_harder_fd(fd, &d);
r = get_block_device_harder_fd(real_fd, &d);
if (r < 0)
return log_error_errno(r, "Failed to determine block device of file system: %m");
} else if (RESOURCE_IS_FILESYSTEM(rr->type)) {
_cleanup_free_ char *resolved = NULL, *relative_to = NULL;
@ -682,9 +730,6 @@ int resource_resolve_path(
} else
return 0; /* Otherwise assume there's nothing to resolve */
if (r < 0)
return log_error_errno(r, "Failed to determine block device of file system: %m");
r = block_get_whole_disk(d, &d);
if (r < 0)
return log_error_errno(r, "Failed to find whole disk device for partition backing file system: %m");