diff --git a/3468542f-virFileUnlink.patch b/3468542f-virFileUnlink.patch new file mode 100644 index 0000000..f152f3a --- /dev/null +++ b/3468542f-virFileUnlink.patch @@ -0,0 +1,179 @@ +From 3468542f06f6f5dc94defa1603c6a6adea3e2da8 Mon Sep 17 00:00:00 2001 +From: John Ferlan +Date: Mon, 24 Aug 2015 17:00:02 -0400 +Subject: [PATCH] virfile: Introduce virFileUnlink + +In an NFS root-squashed environment the 'vol-delete' command will fail to +'unlink' the target volume since it was created under a different uid:gid. + +This code continues the concepts introduced in virFileOpenForked and +virDirCreate[NoFork] with respect to running the unlink command under +the uid/gid of the child. Unlike the other two, don't retry on EACCES +(that's why we're here doing this now). + +(cherry picked from commit 35847860f65f92e444db9730e00cdaef45198e0c) +--- + src/libvirt_private.syms | 1 + + src/storage/storage_backend_fs.c | 3 +- + src/util/virfile.c | 106 +++++++++++++++++++++++++++++++++++++++ + src/util/virfile.h | 1 + + 4 files changed, 110 insertions(+), 1 deletion(-) + +diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms +index d57bf5b..a96c985 100644 +--- a/src/libvirt_private.syms ++++ b/src/libvirt_private.syms +@@ -1462,6 +1462,7 @@ virFileSanitizePath; + virFileSkipRoot; + virFileStripSuffix; + virFileTouch; ++virFileUnlink; + virFileUnlock; + virFileUpdatePerm; + virFileWaitForDevices; +diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c +index c0ea1df..f41a41e 100644 +--- a/src/storage/storage_backend_fs.c ++++ b/src/storage/storage_backend_fs.c +@@ -1203,7 +1203,8 @@ virStorageBackendFileSystemVolDelete(virConnectPtr conn ATTRIBUTE_UNUSED, + + switch ((virStorageVolType) vol->type) { + case VIR_STORAGE_VOL_FILE: +- if (unlink(vol->target.path) < 0) { ++ if (virFileUnlink(vol->target.path, vol->target.perms->uid, ++ vol->target.perms->gid) < 0) { + /* Silently ignore failures where the vol has already gone away */ + if (errno != ENOENT) { + virReportSystemError(errno, +diff --git a/src/util/virfile.c b/src/util/virfile.c +index 5f64186..7b14ee8 100644 +--- a/src/util/virfile.c ++++ b/src/util/virfile.c +@@ -2306,6 +2306,112 @@ virFileOpenAs(const char *path, int openflags, mode_t mode, + return ret; + } + ++ ++/* virFileUnlink: ++ * @path: file to unlink ++ * @uid: uid that was used to create the file (not required) ++ * @gid: gid that was used to create the file (not required) ++ * ++ * If a file/volume was created in an NFS root-squash environment, ++ * then we must 'unlink' the file in the same environment. Unlike ++ * the virFileOpenAs[Forked] and virDirCreate[NoFork], this code ++ * takes no extra flags and does not bother with EACCES failures ++ * from the child. ++ */ ++int ++virFileUnlink(const char *path, ++ uid_t uid, ++ gid_t gid) ++{ ++ pid_t pid; ++ int waitret; ++ int status, ret = 0; ++ gid_t *groups; ++ int ngroups; ++ ++ /* If not running as root or if a non explicit uid/gid was being used for ++ * the file/volume, then use unlink directly ++ */ ++ if ((geteuid() != 0) || ++ ((uid == (uid_t) -1) && (gid == (gid_t) -1))) ++ return unlink(path); ++ ++ /* Otherwise, we have to deal with the NFS root-squash craziness ++ * to run under the uid/gid that created the volume in order to ++ * perform the unlink of the volume. ++ */ ++ if (uid == (uid_t) -1) ++ uid = geteuid(); ++ if (gid == (gid_t) -1) ++ gid = getegid(); ++ ++ ngroups = virGetGroupList(uid, gid, &groups); ++ if (ngroups < 0) ++ return -errno; ++ ++ pid = virFork(); ++ ++ if (pid < 0) { ++ ret = -errno; ++ VIR_FREE(groups); ++ return ret; ++ } ++ ++ if (pid) { /* parent */ ++ /* wait for child to complete, and retrieve its exit code */ ++ VIR_FREE(groups); ++ ++ while ((waitret = waitpid(pid, &status, 0)) == -1 && errno == EINTR); ++ if (waitret == -1) { ++ ret = -errno; ++ virReportSystemError(errno, ++ _("failed to wait for child unlinking '%s'"), ++ path); ++ goto parenterror; ++ } ++ ++ /* ++ * If waitpid succeeded, but if the child exited abnormally or ++ * reported non-zero status, report failure ++ */ ++ if (!WIFEXITED(status) || (WEXITSTATUS(status)) != 0) { ++ char *msg = virProcessTranslateStatus(status); ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("child failed to unlink '%s': %s"), ++ path, msg); ++ VIR_FREE(msg); ++ if (WIFEXITED(status)) ++ ret = -WEXITSTATUS(status); ++ else ++ ret = -EACCES; ++ } ++ ++ parenterror: ++ return ret; ++ } ++ ++ /* child */ ++ ++ /* set desired uid/gid, then attempt to unlink the file */ ++ if (virSetUIDGID(uid, gid, groups, ngroups) < 0) { ++ ret = errno; ++ goto childerror; ++ } ++ ++ if (unlink(path) < 0) { ++ ret = errno; ++ goto childerror; ++ } ++ ++ childerror: ++ if ((ret & 0xff) != ret) { ++ VIR_WARN("unable to pass desired return value %d", ret); ++ ret = 0xff; ++ } ++ _exit(ret); ++} ++ ++ + /* return -errno on failure, or 0 on success */ + static int + virDirCreateNoFork(const char *path, +diff --git a/src/util/virfile.h b/src/util/virfile.h +index 2d27e89..797ca65 100644 +--- a/src/util/virfile.h ++++ b/src/util/virfile.h +@@ -219,6 +219,7 @@ int virFileOpenAs(const char *path, int openflags, mode_t mode, + uid_t uid, gid_t gid, + unsigned int flags) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; ++int virFileUnlink(const char *path, uid_t uid, gid_t gid); + + enum { + VIR_DIR_CREATE_NONE = 0, +-- +2.1.4 + diff --git a/8b1d84e6-refreshVol-failure.patch b/8b1d84e6-refreshVol-failure.patch new file mode 100644 index 0000000..ca42d07 --- /dev/null +++ b/8b1d84e6-refreshVol-failure.patch @@ -0,0 +1,39 @@ +From 8b1d84e640f1a6e6ebb47caf23a664e2f651b32d Mon Sep 17 00:00:00 2001 +From: John Ferlan +Date: Mon, 24 Aug 2015 12:38:13 -0400 +Subject: [PATCH] storage: Handle failure from refreshVol + +Commit id '155ca616' added the 'refreshVol' API. In an NFS root-squash +environment it was possible that if the just created volume from XML wasn't +properly created with the right uid/gid and/or mode, then the followup +refreshVol will fail to open the volume in order to get the allocation/ +capacity values. This would leave the volume still on the server and +cause a libvirtd crash because 'voldef' would be in the pool list, but +the cleanup code would free it. + +(cherry picked from commit db9277a39bc364806e8d3e08a08fc128d59b7094) +--- + src/storage/storage_driver.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c +index ea7e0f3..0494e5d 100644 +--- a/src/storage/storage_driver.c ++++ b/src/storage/storage_driver.c +@@ -1867,8 +1867,12 @@ storageVolCreateXML(virStoragePoolPtr obj, + } + + if (backend->refreshVol && +- backend->refreshVol(obj->conn, pool, voldef) < 0) ++ backend->refreshVol(obj->conn, pool, voldef) < 0) { ++ storageVolDeleteInternal(volobj, backend, pool, voldef, ++ 0, false); ++ voldef = NULL; + goto cleanup; ++ } + + /* Update pool metadata ignoring the disk backend since + * it updates the pool values. +-- +2.1.4 + diff --git a/ba25c214-libxl-log-level.patch b/ba25c214-libxl-log-level.patch new file mode 100644 index 0000000..a538721 --- /dev/null +++ b/ba25c214-libxl-log-level.patch @@ -0,0 +1,51 @@ +commit ba25c214f7c622c75448e760f3204844cfff50d0 +Author: Jim Fehlig +Date: Tue Sep 15 08:17:44 2015 -0600 + + libxl: open libxl log stream with libvirtd log_level + + Instead of a hardcoded DEBUG log level, use the overall + daemon log level specified in libvirtd.conf when opening + a log stream with libxl. libxl is very verbose when DEBUG + log level is set, resulting in huge log files that can + potentially fill a disk. Control of libxl verbosity should + be placed in the administrator's hands. + +Index: libvirt-1.2.18/src/libxl/libxl_conf.c +=================================================================== +--- libvirt-1.2.18.orig/src/libxl/libxl_conf.c ++++ libvirt-1.2.18/src/libxl/libxl_conf.c +@@ -1495,6 +1495,7 @@ libxlDriverConfigNew(void) + { + libxlDriverConfigPtr cfg; + char *log_file = NULL; ++ xentoollog_level log_level; + char ebuf[1024]; + unsigned int free_mem; + +@@ -1539,9 +1540,24 @@ libxlDriverConfigNew(void) + } + VIR_FREE(log_file); + ++ switch (virLogGetDefaultPriority()) { ++ case VIR_LOG_DEBUG: ++ log_level = XTL_DEBUG; ++ break; ++ case VIR_LOG_INFO: ++ log_level = XTL_INFO; ++ break; ++ case VIR_LOG_WARN: ++ log_level = XTL_WARN; ++ break; ++ case VIR_LOG_ERROR: ++ log_level = XTL_ERROR; ++ break; ++ } ++ + cfg->logger = + (xentoollog_logger *)xtl_createlogger_stdiostream(cfg->logger_file, +- XTL_DEBUG, XTL_STDIOSTREAM_SHOW_DATE); ++ log_level, XTL_STDIOSTREAM_SHOW_DATE); + if (!cfg->logger) { + VIR_ERROR(_("cannot create logger for libxenlight, disabling driver")); + goto error; diff --git a/e0025d29-storage-mode-check.patch b/e0025d29-storage-mode-check.patch new file mode 100644 index 0000000..c4de908 --- /dev/null +++ b/e0025d29-storage-mode-check.patch @@ -0,0 +1,49 @@ +From e0025d2967bbe3f283937216c9e2c12b6e9d1010 Mon Sep 17 00:00:00 2001 +From: John Ferlan +Date: Mon, 24 Aug 2015 12:48:40 -0400 +Subject: [PATCH] storage: Correct the 'mode' check + +Commit id '7c2d65dde2' changed the default value of mode to be -1 if not +supplied in the XML, which should cause creation of the volume using the +default mode of VIR_STORAGE_DEFAULT_VOL_PERM_MODE; however, the check +made was whether mode was '0' or not to use default or provided value. + +This patch fixes the issue to check if the 'mode' was provided in the XML +and use that value. + +(cherry picked from commit 691dd388aee99f8b06177540303b690586d5f5b3) +--- + src/storage/storage_backend.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c +index 0418473..6a3146c 100644 +--- a/src/storage/storage_backend.c ++++ b/src/storage/storage_backend.c +@@ -486,6 +486,7 @@ virStorageBackendCreateRaw(virConnectPtr conn ATTRIBUTE_UNUSED, + int fd = -1; + int operation_flags; + bool reflink_copy = false; ++ mode_t open_mode = VIR_STORAGE_DEFAULT_VOL_PERM_MODE; + + virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA | + VIR_STORAGE_VOL_CREATE_REFLINK, +@@ -518,11 +519,12 @@ virStorageBackendCreateRaw(virConnectPtr conn ATTRIBUTE_UNUSED, + if (pool->def->type == VIR_STORAGE_POOL_NETFS) + operation_flags |= VIR_FILE_OPEN_FORK; + ++ if (vol->target.perms->mode != (mode_t) -1) ++ open_mode = vol->target.perms->mode; ++ + if ((fd = virFileOpenAs(vol->target.path, + O_RDWR | O_CREAT | O_EXCL, +- (vol->target.perms->mode ? +- VIR_STORAGE_DEFAULT_VOL_PERM_MODE : +- vol->target.perms->mode), ++ open_mode, + vol->target.perms->uid, + vol->target.perms->gid, + operation_flags)) < 0) { +-- +2.1.4 + diff --git a/libvirt.changes b/libvirt.changes index 33511d8..62ba572 100644 --- a/libvirt.changes +++ b/libvirt.changes @@ -1,3 +1,20 @@ +------------------------------------------------------------------- +Tue Sep 15 17:37:36 UTC 2015 - jfehlig@suse.com + +- libxl: set driver log level to the log_level specified in + libvirtd.conf + ba25c214-libxl-log-level.patch + bsc#945796 + +------------------------------------------------------------------- +Mon Sep 14 08:18:12 UTC 2015 - cbosdonnat@suse.com + +- CVE-2015-5247 - denial of service through root-squash NFS storage + bsc#945645 + 3468542f-virFileUnlink.patch + 8b1d84e6-refreshVol-failure.patch + e0025d29-storage-mode-check.patch + ------------------------------------------------------------------- Wed Sep 2 06:14:17 UTC 2015 - jfehlig@suse.com diff --git a/libvirt.spec b/libvirt.spec index 527a63e..71c694a 100644 --- a/libvirt.spec +++ b/libvirt.spec @@ -446,6 +446,10 @@ Source3: libvirtd.init Source4: libvirtd-relocation-server.fw Source99: baselibs.conf # Upstream patches +Patch0: 3468542f-virFileUnlink.patch +Patch1: 8b1d84e6-refreshVol-failure.patch +Patch2: e0025d29-storage-mode-check.patch +Patch3: ba25c214-libxl-log-level.patch # Patches pending upstream review # Need to go upstream Patch150: xen-pv-cdrom.patch @@ -976,6 +980,10 @@ Provides a dissector for the libvirt RPC protocol to help debugging it. %prep %setup -q +%patch0 -p1 +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 %patch150 -p1 %patch151 -p1 %patch152 -p1