diff --git a/libvirt-util-virFileChownFiles-do-not-follow-symlinks.patch b/libvirt-util-virFileChownFiles-do-not-follow-symlinks.patch new file mode 100644 index 0000000..3c09abb --- /dev/null +++ b/libvirt-util-virFileChownFiles-do-not-follow-symlinks.patch @@ -0,0 +1,70 @@ +From c5d4c048cb82d6a13a440adbfd89462300902f63 Mon Sep 17 00:00:00 2001 +Message-ID: +From: =?UTF-8?q?HE=20WEI=EF=BC=88=E3=82=AE=E3=82=AB=E3=82=AF=EF=BC=89?= + +Date: Tue, 28 Jul 2026 17:49:02 +0100 +Subject: [PATCH] util: virFileChownFiles: do not follow symlinks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +virFileChownFiles() selected entries with virFileIsRegular() (stat(), follows +symlinks) and changed ownership with chown() (follows symlinks). A component +that owns the target directory at a lower privilege (e.g. the swtpm/tss state +directory) can plant a symlink to an arbitrary regular file and have the root +caller chown that file. Use lstat() to skip non-regular entries and +fchownat(..., AT_SYMLINK_NOFOLLOW) so a symlink final component is never +followed. + +Fixes: CVE-2026-63622 +Signed-off-by: HE WEI(ギカク) +[DB: use g_lstat instead of stat; use lchown instead of + fchownat for portability; added comment] +Reviewed-by: Ján Tomko +Signed-off-by: Daniel P. Berrangé +(cherry picked from commit 801160fd414ca2cc402bc01ead09b7ed4c3b8f5b) +--- + src/util/virfile.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/src/util/virfile.c b/src/util/virfile.c +index d6faf7e3d2..e2f30b9fe6 100644 +--- a/src/util/virfile.c ++++ b/src/util/virfile.c +@@ -2935,6 +2935,12 @@ void virDirClose(DIR *dirp) + * + * Change ownership of all regular files in a directory. + * ++ * This will NOT follow any symlinks, to avoid security risks. ++ * It is assumed the process using content under @name will ++ * be unprivileged, thus less trusted than libvirt. If it is ++ * compromised it might attempt to create symlinks in @name to ++ * escalate privileges on a subsequent call to virFileChownFiles. ++ * + * Returns -1 on error, with error already reported, 0 on success. + */ + #ifndef WIN32 +@@ -2951,13 +2957,19 @@ int virFileChownFiles(const char *name, + + while ((direrr = virDirRead(dir, &ent, name)) > 0) { + g_autofree char *path = NULL; ++ struct stat sb; + + path = g_build_filename(name, ent->d_name, NULL); + +- if (!virFileIsRegular(path)) ++ if (g_lstat(path, &sb) < 0) { ++ virReportSystemError(errno, _("cannot stat '%1$s'"), path); ++ return -1; ++ } ++ ++ if (!S_ISREG(sb.st_mode)) + continue; + +- if (chown(path, uid, gid) < 0) { ++ if (lchown(path, uid, gid) < 0) { + virReportSystemError(errno, + _("cannot chown '%s' to (%u, %u)"), + ent->d_name, (unsigned int) uid, +-- +2.55.0 diff --git a/libvirt.spec b/libvirt.spec index a5fa0f4..3bdb45f 100644 --- a/libvirt.spec +++ b/libvirt.spec @@ -210,7 +210,7 @@ Summary: Library providing a simple virtualization API Name: libvirt Version: 8.0.0 -Release: 23.7%{?dist}%{?extra_release} +Release: 23.8%{?dist}%{?extra_release} License: LGPLv2+ URL: https://libvirt.org/ @@ -336,6 +336,7 @@ Patch113: libvirt-services-Weaken-systemd-dependency-on-virtlockd.patch Patch114: libvirt-qemu-Ensure-proper-shutdown-ordering-of-virtlockd-virtlogd-daemons.patch Patch115: libvirt-qemu-Fix-proper-ordering-of-virtlockd-shutdown.patch Patch116: libvirt-remote-Fix-integer-overflow-in-RPC-handler-for-virNodeGetFreePages-CVE-2026-18917.patch +Patch117: libvirt-util-virFileChownFiles-do-not-follow-symlinks.patch Requires: libvirt-daemon = %{version}-%{release} Requires: libvirt-daemon-config-network = %{version}-%{release} @@ -2215,6 +2216,9 @@ exit 0 %changelog +* Mon Aug 31 2026 Jiri Denemark - 8.0.0-23.8.el8 +- util: virFileChownFiles: do not follow symlinks (CVE-2026-63622) + * Fri Aug 21 2026 Jiri Denemark - 8.0.0-23.7.el8 - remote: Fix integer overflow in RPC handler for virNodeGetFreePages (CVE-2026-18917) (RHEL-245267)