libvirt-11.10.0-2.el9
- qemu: tpm: Account for possible migration without actually sharing storage (RHEL-108915) - tests: Test virFileIsSharedFSOverride (RHEL-135287) - util: Fix race condition in virFileIsSharedFSType (RHEL-135287) - util: Fix race condition in virFileIsSharedFSOverride (RHEL-135287) - util: Rework virFileIsSharedFSOverride using virFileCheckParents (RHEL-135287) Resolves: RHEL-108915, RHEL-135287
This commit is contained in:
parent
14c96f4934
commit
a3cafd28ee
@ -0,0 +1,119 @@
|
||||
From 582ac1d5b308d1b9816c57ebca762a8796c67df4 Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <582ac1d5b308d1b9816c57ebca762a8796c67df4.1766070256.git.jdenemar@redhat.com>
|
||||
From: Peter Krempa <pkrempa@redhat.com>
|
||||
Date: Mon, 1 Dec 2025 11:35:32 +0100
|
||||
Subject: [PATCH] qemu: tpm: Account for possible migration without actually
|
||||
sharing storage
|
||||
|
||||
The current logic in 'qemuTPMEmulatorBuildCommand' skips all setup if
|
||||
the *location* of the data is on what we'd consider shared storage.
|
||||
|
||||
This means that if the location is not actually shared (e.g. it's shared
|
||||
betweeh some other hosts than the two doing the migration) and the path
|
||||
wasn't ever used (e.g. by migrating out) from the host where we're
|
||||
migrating into the complete setup of the location would be skipped even
|
||||
when it doesn't exist.
|
||||
|
||||
Fix the logic by skipping only some of the setup steps so that
|
||||
'qemuTPMEmulatorCreateStorage' can still create the storage if it
|
||||
doesn't exist.
|
||||
|
||||
The rest of the code then needs to take the 'created' flag returned from
|
||||
'qemuTPMEmulatorCreateStorage' into account.
|
||||
|
||||
Fixes: 68103e9daf633b789428fedef56f816c92f6ee75
|
||||
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
|
||||
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
|
||||
(cherry picked from commit d56d0560946770d4364a4918cc289e6a7fe5d15c)
|
||||
https://issues.redhat.com/browse/RHEL-108915
|
||||
---
|
||||
src/qemu/qemu_tpm.c | 29 ++++++++++++++++++++---------
|
||||
1 file changed, 20 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c
|
||||
index 4c9445d72c..660410bcba 100644
|
||||
--- a/src/qemu/qemu_tpm.c
|
||||
+++ b/src/qemu/qemu_tpm.c
|
||||
@@ -158,6 +158,7 @@ qemuTPMEmulatorGetPid(const char *swtpmStateDir,
|
||||
/**
|
||||
* qemuTPMEmulatorCreateStorage:
|
||||
* @tpm: TPM definition for an emulator type
|
||||
+ * @sharedStorageMigration: VM is being migrated with possibly shared storage
|
||||
* @created: a pointer to a bool that will be set to true if the
|
||||
* storage was created because it did not exist yet
|
||||
* @swtpm_user: The uid that needs to be able to access the directory
|
||||
@@ -169,6 +170,7 @@ qemuTPMEmulatorGetPid(const char *swtpmStateDir,
|
||||
*/
|
||||
static int
|
||||
qemuTPMEmulatorCreateStorage(virDomainTPMDef *tpm,
|
||||
+ bool sharedStorageMigration,
|
||||
bool *created,
|
||||
uid_t swtpm_user,
|
||||
gid_t swtpm_group)
|
||||
@@ -187,8 +189,17 @@ qemuTPMEmulatorCreateStorage(virDomainTPMDef *tpm,
|
||||
*created = false;
|
||||
|
||||
if (!virFileExists(source_path) ||
|
||||
- virDirIsEmpty(source_path, true) > 0)
|
||||
+ virDirIsEmpty(source_path, true) > 0) {
|
||||
*created = true;
|
||||
+ } else {
|
||||
+ /* If the location exists and is shared, we don't need to create it
|
||||
+ * during migration */
|
||||
+ if (sharedStorageMigration) {
|
||||
+ VIR_DEBUG("Skipping TPM storage creation. Path '%s' already exists and is on shared storage.",
|
||||
+ source_path);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
if (virDirCreate(source_path, 0700, swtpm_user, swtpm_group,
|
||||
VIR_DIR_CREATE_ALLOW_EXIST) < 0) {
|
||||
@@ -809,16 +820,13 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm,
|
||||
run_setup = true;
|
||||
}
|
||||
|
||||
- /* Do not create storage and run swtpm_setup on incoming migration over
|
||||
- * shared storage
|
||||
- */
|
||||
on_shared_storage = virFileIsSharedFS(tpm->data.emulator.source_path,
|
||||
cfg->sharedFilesystems) == 1;
|
||||
- if (incomingMigration && on_shared_storage)
|
||||
- create_storage = false;
|
||||
|
||||
if (create_storage) {
|
||||
- if (qemuTPMEmulatorCreateStorage(tpm, &created,
|
||||
+ if (qemuTPMEmulatorCreateStorage(tpm,
|
||||
+ incomingMigration && on_shared_storage,
|
||||
+ &created,
|
||||
cfg->swtpm_user, cfg->swtpm_group) < 0)
|
||||
return NULL;
|
||||
run_setup = created;
|
||||
@@ -885,6 +893,9 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm,
|
||||
/* If swtpm supports it and the TPM state is stored on shared storage,
|
||||
* start swtpm with --migration release-lock-outgoing so it can migrate
|
||||
* across shared storage if needed.
|
||||
+ *
|
||||
+ * Note that if 'created' is true, the location didn't exist so the storage
|
||||
+ * is not actually shared.
|
||||
*/
|
||||
QEMU_DOMAIN_TPM_PRIVATE(tpm)->swtpm.can_migrate_shared_storage = false;
|
||||
if (on_shared_storage &&
|
||||
@@ -892,13 +903,13 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm,
|
||||
|
||||
virCommandAddArg(cmd, "--migration");
|
||||
virCommandAddArgFormat(cmd, "release-lock-outgoing%s",
|
||||
- incomingMigration ? ",incoming": "");
|
||||
+ incomingMigration && !created ? ",incoming": "");
|
||||
QEMU_DOMAIN_TPM_PRIVATE(tpm)->swtpm.can_migrate_shared_storage = true;
|
||||
} else {
|
||||
/* Report an error if there's an incoming migration across shared
|
||||
* storage and swtpm does not support the --migration option.
|
||||
*/
|
||||
- if (incomingMigration && on_shared_storage) {
|
||||
+ if (incomingMigration && on_shared_storage && !created) {
|
||||
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
|
||||
_("%1$s (on destination side) does not support the --migration option needed for migration with shared storage"),
|
||||
swtpm);
|
||||
--
|
||||
2.52.0
|
||||
111
libvirt-tests-Test-virFileIsSharedFSOverride.patch
Normal file
111
libvirt-tests-Test-virFileIsSharedFSOverride.patch
Normal file
@ -0,0 +1,111 @@
|
||||
From b630429647207ba0d406cf855e590ddaa98fdb9b Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <b630429647207ba0d406cf855e590ddaa98fdb9b.1766070256.git.jdenemar@redhat.com>
|
||||
From: Jiri Denemark <jdenemar@redhat.com>
|
||||
Date: Fri, 5 Dec 2025 15:09:15 +0100
|
||||
Subject: [PATCH] tests: Test virFileIsSharedFSOverride
|
||||
|
||||
Technically virFileIsSharedFSOverride is available on any OS, but we
|
||||
need a mocked realpath() to test it. Because the virfilemock library
|
||||
also mocks statfs() which is only available on Linux, we don't even try
|
||||
to load the library anywhere else. Thus we need to skip testing
|
||||
virFileIsSharedFSOverride on non-Linux too.
|
||||
|
||||
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
||||
(cherry picked from commit 121d179e068b584f62ea2c029d89a44e67c909c0)
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-135287
|
||||
|
||||
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
||||
---
|
||||
tests/virfiletest.c | 69 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 69 insertions(+)
|
||||
|
||||
diff --git a/tests/virfiletest.c b/tests/virfiletest.c
|
||||
index e05925a321..ccd76a3fac 100644
|
||||
--- a/tests/virfiletest.c
|
||||
+++ b/tests/virfiletest.c
|
||||
@@ -329,6 +329,55 @@ testFileIsSharedFSType(const void *opaque G_GNUC_UNUSED)
|
||||
}
|
||||
|
||||
|
||||
+static const char *shared_filesystems[] = {
|
||||
+ "/run/user/501/gvfs",
|
||||
+ "/nfs",
|
||||
+ "/gluster",
|
||||
+ "/ceph/multi",
|
||||
+ "/gpfs/data/blaf",
|
||||
+ "/quobyte",
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
+static int
|
||||
+testFileIsSharedFSOverride(const void *opaque G_GNUC_UNUSED)
|
||||
+{
|
||||
+#ifndef __linux__
|
||||
+ return EXIT_AM_SKIP;
|
||||
+#else
|
||||
+ const struct testFileIsSharedFSType *data = opaque;
|
||||
+ g_autofree char *mtabFile = NULL;
|
||||
+ bool actual;
|
||||
+ int ret = -1;
|
||||
+
|
||||
+ /* mtab is used by mocked realpath to decide whether a given path exists */
|
||||
+ mtabFile = g_strdup_printf(abs_srcdir "/virfiledata/%s", data->mtabFile);
|
||||
+
|
||||
+ if (!g_setenv("LIBVIRT_MTAB", mtabFile, true)) {
|
||||
+ fprintf(stderr, "Unable to set env variable\n");
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ actual = virFileIsSharedFSOverride(data->filename,
|
||||
+ (char * const *) shared_filesystems);
|
||||
+
|
||||
+ if (actual != data->expected) {
|
||||
+ fprintf(stderr, "FS of '%s' is %s. Expected: %s\n",
|
||||
+ data->filename,
|
||||
+ actual ? "shared" : "not shared",
|
||||
+ data->expected ? "shared" : "not shared");
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
+
|
||||
+ ret = 0;
|
||||
+
|
||||
+ cleanup:
|
||||
+ g_unsetenv("LIBVIRT_MTAB");
|
||||
+ return ret;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+
|
||||
static int
|
||||
mymain(void)
|
||||
{
|
||||
@@ -439,6 +488,26 @@ mymain(void)
|
||||
DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/gpfs/data", true);
|
||||
DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/quobyte", true);
|
||||
|
||||
+#define DO_TEST_FILE_IS_SHARED_FS_OVERRIDE(mtab, file, exp) \
|
||||
+ do { \
|
||||
+ struct testFileIsSharedFSType data = { \
|
||||
+ .mtabFile = mtab, .filename = file, .expected = exp \
|
||||
+ }; \
|
||||
+ if (virTestRun(virTestCounterNext(), testFileIsSharedFSOverride, &data) < 0) \
|
||||
+ ret = -1; \
|
||||
+ } while (0)
|
||||
+
|
||||
+ virTestCounterReset("testFileIsSharedFSOverride ");
|
||||
+ DO_TEST_FILE_IS_SHARED_FS_OVERRIDE("mounts2.txt", "/boot/vmlinuz", false);
|
||||
+ DO_TEST_FILE_IS_SHARED_FS_OVERRIDE("mounts2.txt", "/run/user/501/gvfs/some/file", true);
|
||||
+ DO_TEST_FILE_IS_SHARED_FS_OVERRIDE("mounts3.txt", "/nfs/file", true);
|
||||
+ DO_TEST_FILE_IS_SHARED_FS_OVERRIDE("mounts3.txt", "/gluster/file", true);
|
||||
+ DO_TEST_FILE_IS_SHARED_FS_OVERRIDE("mounts3.txt", "/some/symlink/file", true);
|
||||
+ DO_TEST_FILE_IS_SHARED_FS_OVERRIDE("mounts3.txt", "/ceph/file", false);
|
||||
+ DO_TEST_FILE_IS_SHARED_FS_OVERRIDE("mounts3.txt", "/ceph/multi/file", true);
|
||||
+ DO_TEST_FILE_IS_SHARED_FS_OVERRIDE("mounts3.txt", "/gpfs/data", false);
|
||||
+ DO_TEST_FILE_IS_SHARED_FS_OVERRIDE("mounts3.txt", "/quobyte", true);
|
||||
+
|
||||
return ret != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
--
|
||||
2.52.0
|
||||
@ -0,0 +1,114 @@
|
||||
From 7f7d60e42f39deaec69318b93cf922f1dda54a26 Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <7f7d60e42f39deaec69318b93cf922f1dda54a26.1766070256.git.jdenemar@redhat.com>
|
||||
From: Jiri Denemark <jdenemar@redhat.com>
|
||||
Date: Fri, 5 Dec 2025 16:51:25 +0100
|
||||
Subject: [PATCH] util: Fix race condition in virFileIsSharedFSOverride
|
||||
|
||||
Switch virFileIsSharedFSOverride to use virFileCheckParents to avoid a
|
||||
race which could result in virFileCanonicalizePath to be called on a
|
||||
path that does not exist anymore.
|
||||
|
||||
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
||||
(cherry picked from commit 3a44f0c23d75519a9a374f790f4b91ab7b65a138)
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-135287
|
||||
|
||||
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
||||
---
|
||||
src/util/virfile.c | 59 +++++++++++++++++-----------------------------
|
||||
1 file changed, 22 insertions(+), 37 deletions(-)
|
||||
|
||||
diff --git a/src/util/virfile.c b/src/util/virfile.c
|
||||
index 95fc8ff0e6..52d711d2a9 100644
|
||||
--- a/src/util/virfile.c
|
||||
+++ b/src/util/virfile.c
|
||||
@@ -3502,33 +3502,6 @@ virFileCheckParents(const char *path,
|
||||
}
|
||||
|
||||
|
||||
-static char *
|
||||
-virFileGetExistingParent(const char *path)
|
||||
-{
|
||||
- g_autofree char *dirpath = g_strdup(path);
|
||||
- char *p = NULL;
|
||||
-
|
||||
- /* Try less and less of the path until we get to a directory we can access.
|
||||
- * Even if we don't have 'x' permission on any directory in the path on the
|
||||
- * NFS server (assuming it's NFS), we will be able to stat the mount point.
|
||||
- */
|
||||
- while (!virFileExists(dirpath) && p != dirpath) {
|
||||
- if (!(p = strrchr(dirpath, '/'))) {
|
||||
- virReportSystemError(EINVAL,
|
||||
- _("Invalid relative path '%1$s'"), path);
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
- if (p == dirpath)
|
||||
- *(p + 1) = '\0';
|
||||
- else
|
||||
- *p = '\0';
|
||||
- }
|
||||
-
|
||||
- return g_steal_pointer(&dirpath);
|
||||
-}
|
||||
-
|
||||
-
|
||||
#ifdef __linux__
|
||||
|
||||
# ifndef NFS_SUPER_MAGIC
|
||||
@@ -3875,6 +3848,17 @@ virFileGetDefaultHugepage(virHugeTLBFS *fs,
|
||||
}
|
||||
|
||||
|
||||
+static bool
|
||||
+virFileCheckParentsCanonicalize(const char *path,
|
||||
+ void *opaque)
|
||||
+{
|
||||
+ char **canonical = opaque;
|
||||
+
|
||||
+ *canonical = virFileCanonicalizePath(path);
|
||||
+ return !!*canonical;
|
||||
+}
|
||||
+
|
||||
+
|
||||
/**
|
||||
* virFileIsSharedFSOverride:
|
||||
* @path: Path to check
|
||||
@@ -3888,24 +3872,25 @@ virFileIsSharedFSOverride(const char *path,
|
||||
char *const *overrides)
|
||||
{
|
||||
g_autofree char *dirpath = NULL;
|
||||
- g_autofree char *existing = NULL;
|
||||
char *p = NULL;
|
||||
+ int rc;
|
||||
|
||||
if (!path || path[0] != '/' || !overrides)
|
||||
return false;
|
||||
|
||||
/* We only care about the longest existing sub-path. Further components
|
||||
- * may will later be created by libvirt will not magically become a shared
|
||||
- * filesystem. */
|
||||
- if (!(existing = virFileGetExistingParent(path)))
|
||||
+ * that may later be created by libvirt will not magically become a shared
|
||||
+ * filesystem. Overrides have been canonicalized ahead of time, so we need
|
||||
+ * to do the same for the provided path or we'll never be able to find a
|
||||
+ * match if symlinks are involved.
|
||||
+ */
|
||||
+ rc = virFileCheckParents(path, NULL,
|
||||
+ virFileCheckParentsCanonicalize, &dirpath);
|
||||
+ if (rc == -1)
|
||||
return false;
|
||||
|
||||
- /* Overrides have been canonicalized ahead of time, so we need to
|
||||
- * do the same for the provided path or we'll never be able to
|
||||
- * find a match if symlinks are involved */
|
||||
- if (!(dirpath = virFileCanonicalizePath(existing))) {
|
||||
- VIR_DEBUG("Cannot canonicalize parent '%s' of path '%s'",
|
||||
- existing, path);
|
||||
+ if (rc != 0) {
|
||||
+ VIR_DEBUG("Cannot canonicalize path '%s'", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
--
|
||||
2.52.0
|
||||
144
libvirt-util-Fix-race-condition-in-virFileIsSharedFSType.patch
Normal file
144
libvirt-util-Fix-race-condition-in-virFileIsSharedFSType.patch
Normal file
@ -0,0 +1,144 @@
|
||||
From 4596ee4c2fe33d3b44a44b120d61052ac943bae4 Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <4596ee4c2fe33d3b44a44b120d61052ac943bae4.1766070256.git.jdenemar@redhat.com>
|
||||
From: Jiri Denemark <jdenemar@redhat.com>
|
||||
Date: Fri, 5 Dec 2025 16:47:14 +0100
|
||||
Subject: [PATCH] util: Fix race condition in virFileIsSharedFSType
|
||||
|
||||
virFileIsSharedFSType could end up calling statfs on a path that no
|
||||
longer exists and return an error. If this happens for a path on a
|
||||
shared filesystem, the caller may incorrectly consider the path as
|
||||
non-shared.
|
||||
|
||||
Specifically, when starting a domain with TPM enabled and deciding
|
||||
whether its vTPM state is stored on a shared storage, the race could
|
||||
cause qemuTPMEmulatorBuildCommand to consider the state to be
|
||||
non-shared. This means swtpm would be started without --migration even
|
||||
when the state is actually stored on a shared storage and any attempt to
|
||||
migrate such domain would fail with
|
||||
|
||||
Operation not supported: the running swtpm does not support
|
||||
migration with shared storage
|
||||
|
||||
In fact, any caller of virFileGetExistingParent contained an inherent
|
||||
TOCTOU race condition as the existing parent of a given path return by
|
||||
virFileGetExistingParent may no longer exist at the time the caller
|
||||
wants to check it.
|
||||
|
||||
This patch introduces a new virFileCheckParents API which is almost
|
||||
identical to virFileGetExistingParent, but uses a supplied callback to
|
||||
check each path. This new API is used in virFileIsSharedFSType to avoid
|
||||
the race. The old function will later be completely removed once all
|
||||
callers are switched to the new one.
|
||||
|
||||
Fixes: 05526b50909ff50c16e13a0b5580d41de74e3d59
|
||||
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
||||
(cherry picked from commit b6addd42bece693debbf2e95551a2b4d2e1b453f)
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-135287
|
||||
|
||||
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
||||
---
|
||||
src/util/virfile.c | 71 ++++++++++++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 69 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/util/virfile.c b/src/util/virfile.c
|
||||
index a5c9fbe0d9..95fc8ff0e6 100644
|
||||
--- a/src/util/virfile.c
|
||||
+++ b/src/util/virfile.c
|
||||
@@ -3445,6 +3445,63 @@ virFileRemoveLastComponent(char *path)
|
||||
}
|
||||
|
||||
|
||||
+/* Check callback for virFileCheckParents */
|
||||
+typedef bool (*virFileCheckParentsCallback)(const char *dirpath,
|
||||
+ void *opaque);
|
||||
+
|
||||
+/**
|
||||
+ * virFileCheckParents:
|
||||
+ * @path: path to check
|
||||
+ * @parent: where to store the closest parent satisfying the check
|
||||
+ * @check: callback called on parent paths
|
||||
+ * @opaque: data for the @check callback
|
||||
+ *
|
||||
+ * Calls @check on the @path and its parent paths until it returns true or a
|
||||
+ * root directory is reached. When @check returns true, the @parent (if
|
||||
+ * non-NULL) will be set to a copy of the corresponding path. The caller is
|
||||
+ * responsible for freeing it.
|
||||
+ *
|
||||
+ * Returns 0 on success (@parent set),
|
||||
+ * -1 on invalid input,
|
||||
+ * -2 when no path (including "/") satisfies the @check.
|
||||
+ */
|
||||
+static int
|
||||
+virFileCheckParents(const char *path,
|
||||
+ char **parent,
|
||||
+ virFileCheckParentsCallback check,
|
||||
+ void *opaque)
|
||||
+{
|
||||
+ g_autofree char *dirpath = g_strdup(path);
|
||||
+ char *p = NULL;
|
||||
+ bool checkOK;
|
||||
+
|
||||
+ checkOK = check(dirpath, opaque);
|
||||
+
|
||||
+ while (!checkOK && p != dirpath) {
|
||||
+ if (!(p = strrchr(dirpath, G_DIR_SEPARATOR))) {
|
||||
+ virReportSystemError(EINVAL,
|
||||
+ _("Invalid absolute path '%1$s'"), path);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (p == dirpath)
|
||||
+ *(p + 1) = '\0';
|
||||
+ else
|
||||
+ *p = '\0';
|
||||
+
|
||||
+ checkOK = check(dirpath, opaque);
|
||||
+ }
|
||||
+
|
||||
+ if (!checkOK)
|
||||
+ return -2;
|
||||
+
|
||||
+ if (parent)
|
||||
+ *parent = g_steal_pointer(&dirpath);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
static char *
|
||||
virFileGetExistingParent(const char *path)
|
||||
{
|
||||
@@ -3599,6 +3656,14 @@ static const struct virFileSharedFsData virFileSharedFs[] = {
|
||||
};
|
||||
|
||||
|
||||
+static bool
|
||||
+virFileCheckParentsStatFS(const char *path,
|
||||
+ void *opaque)
|
||||
+{
|
||||
+ return statfs(path, (struct statfs *) opaque) == 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
int
|
||||
virFileIsSharedFSType(const char *path,
|
||||
unsigned int fstypes)
|
||||
@@ -3607,11 +3672,13 @@ virFileIsSharedFSType(const char *path,
|
||||
struct statfs sb;
|
||||
long long f_type = 0;
|
||||
size_t i;
|
||||
+ int rc;
|
||||
|
||||
- if (!(dirpath = virFileGetExistingParent(path)))
|
||||
+ if ((rc = virFileCheckParents(path, &dirpath,
|
||||
+ virFileCheckParentsStatFS, &sb)) == -1)
|
||||
return -1;
|
||||
|
||||
- if (statfs(dirpath, &sb) < 0) {
|
||||
+ if (rc != 0) {
|
||||
virReportSystemError(errno,
|
||||
_("cannot determine filesystem for '%1$s'"),
|
||||
path);
|
||||
--
|
||||
2.52.0
|
||||
@ -0,0 +1,84 @@
|
||||
From d85627338e531618aa72b6039483b0d0a3e3d474 Mon Sep 17 00:00:00 2001
|
||||
Message-ID: <d85627338e531618aa72b6039483b0d0a3e3d474.1766070256.git.jdenemar@redhat.com>
|
||||
From: Jiri Denemark <jdenemar@redhat.com>
|
||||
Date: Fri, 5 Dec 2025 16:52:32 +0100
|
||||
Subject: [PATCH] util: Rework virFileIsSharedFSOverride using
|
||||
virFileCheckParents
|
||||
|
||||
The newly introduced virFileCheckParents is generic enough to be used
|
||||
for checking whether a specific path or any of its parents is included
|
||||
in the overrides array.
|
||||
|
||||
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
||||
(cherry picked from commit eedf9ed68b45585569865604bf2a403670feaf3e)
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-135287
|
||||
|
||||
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
||||
---
|
||||
src/util/virfile.c | 35 ++++++++++++-----------------------
|
||||
1 file changed, 12 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/src/util/virfile.c b/src/util/virfile.c
|
||||
index 52d711d2a9..05b2fa8168 100644
|
||||
--- a/src/util/virfile.c
|
||||
+++ b/src/util/virfile.c
|
||||
@@ -3859,6 +3859,14 @@ virFileCheckParentsCanonicalize(const char *path,
|
||||
}
|
||||
|
||||
|
||||
+static bool
|
||||
+virFileCheckParentsInOverrides(const char *path,
|
||||
+ void *opaque)
|
||||
+{
|
||||
+ return g_strv_contains((const char *const *) opaque, path);
|
||||
+}
|
||||
+
|
||||
+
|
||||
/**
|
||||
* virFileIsSharedFSOverride:
|
||||
* @path: Path to check
|
||||
@@ -3872,7 +3880,6 @@ virFileIsSharedFSOverride(const char *path,
|
||||
char *const *overrides)
|
||||
{
|
||||
g_autofree char *dirpath = NULL;
|
||||
- char *p = NULL;
|
||||
int rc;
|
||||
|
||||
if (!path || path[0] != '/' || !overrides)
|
||||
@@ -3894,29 +3901,11 @@ virFileIsSharedFSOverride(const char *path,
|
||||
return false;
|
||||
}
|
||||
|
||||
- if (g_strv_contains((const char *const *) overrides, dirpath))
|
||||
- return true;
|
||||
+ if (virFileCheckParents(dirpath, NULL, virFileCheckParentsInOverrides,
|
||||
+ (void *) overrides) < 0)
|
||||
+ return false;
|
||||
|
||||
- /* Continue until we've scanned the entire path */
|
||||
- while (p != dirpath) {
|
||||
-
|
||||
- /* Find the last slash */
|
||||
- if ((p = strrchr(dirpath, '/')) == NULL)
|
||||
- break;
|
||||
-
|
||||
- /* Truncate the path by overwriting the slash that we've just
|
||||
- * found with a null byte. If it is the very first slash in
|
||||
- * the path, we need to handle things slightly differently */
|
||||
- if (p == dirpath)
|
||||
- *(p+1) = '\0';
|
||||
- else
|
||||
- *p = '\0';
|
||||
-
|
||||
- if (g_strv_contains((const char *const *) overrides, dirpath))
|
||||
- return true;
|
||||
- }
|
||||
-
|
||||
- return false;
|
||||
+ return true;
|
||||
}
|
||||
|
||||
|
||||
--
|
||||
2.52.0
|
||||
18
libvirt.spec
18
libvirt.spec
@ -294,7 +294,7 @@
|
||||
Summary: Library providing a simple virtualization API
|
||||
Name: libvirt
|
||||
Version: 11.10.0
|
||||
Release: 1%{?dist}%{?extra_release}
|
||||
Release: 2%{?dist}%{?extra_release}
|
||||
License: GPL-2.0-or-later AND LGPL-2.1-only AND LGPL-2.1-or-later AND OFL-1.1
|
||||
URL: https://libvirt.org/
|
||||
|
||||
@ -302,6 +302,12 @@ URL: https://libvirt.org/
|
||||
%define mainturl stable_updates/
|
||||
%endif
|
||||
Source: https://download.libvirt.org/%{?mainturl}libvirt-%{version}.tar.xz
|
||||
Patch1: libvirt-qemu-tpm-Account-for-possible-migration-without-actually-sharing-storage.patch
|
||||
Patch2: libvirt-tests-Test-virFileIsSharedFSOverride.patch
|
||||
Patch3: libvirt-util-Fix-race-condition-in-virFileIsSharedFSType.patch
|
||||
Patch4: libvirt-util-Fix-race-condition-in-virFileIsSharedFSOverride.patch
|
||||
Patch5: libvirt-util-Rework-virFileIsSharedFSOverride-using-virFileCheckParents.patch
|
||||
|
||||
|
||||
Requires: libvirt-daemon = %{version}-%{release}
|
||||
Requires: libvirt-daemon-config-network = %{version}-%{release}
|
||||
@ -1168,6 +1174,9 @@ MinGW Windows libvirt virtualization library.
|
||||
%prep
|
||||
%autosetup -S git_am -N
|
||||
|
||||
%autopatch
|
||||
|
||||
|
||||
%build
|
||||
%if 0%{?fedora} >= %{min_fedora} || 0%{?rhel} >= %{min_rhel}
|
||||
%define supported_platform 1
|
||||
@ -2689,6 +2698,13 @@ exit 0
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Thu Dec 18 2025 Jiri Denemark <jdenemar@redhat.com> - 11.10.0-2
|
||||
- qemu: tpm: Account for possible migration without actually sharing storage (RHEL-108915)
|
||||
- tests: Test virFileIsSharedFSOverride (RHEL-135287)
|
||||
- util: Fix race condition in virFileIsSharedFSType (RHEL-135287)
|
||||
- util: Fix race condition in virFileIsSharedFSOverride (RHEL-135287)
|
||||
- util: Rework virFileIsSharedFSOverride using virFileCheckParents (RHEL-135287)
|
||||
|
||||
* Tue Dec 2 2025 Jiri Denemark <jdenemar@redhat.com> - 11.10.0-1
|
||||
- Rebased to libvirt-11.10.0 (RHEL-118197)
|
||||
- The rebase also fixes the following bugs:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user