render / rpms / libvirt

Forked from rpms/libvirt 10 months ago
Clone
c401cc
From 550d1e1b2d5130a95bf78bb224dad8ae8108a53e Mon Sep 17 00:00:00 2001
c401cc
Message-Id: <550d1e1b2d5130a95bf78bb224dad8ae8108a53e@dist-git>
c401cc
From: Eric Blake <eblake@redhat.com>
c401cc
Date: Tue, 18 Feb 2014 15:45:30 -0700
c401cc
Subject: [PATCH] storage: avoid short reads while chasing backing chain
c401cc
c401cc
https://bugzilla.redhat.com/show_bug.cgi?id=1045643
c401cc
prereq of CVE-2013-6456
c401cc
c401cc
Our backing file chain code was not very robust to an ill-timed
c401cc
EINTR, which could lead to a short read causing us to randomly
c401cc
treat metadata differently than usual.  But the existing
c401cc
virFileReadLimFD forces an error if we don't read the entire
c401cc
file, even though we only care about the header of the file.
c401cc
So add a new virFile function that does what we want.
c401cc
c401cc
* src/util/virfile.h (virFileReadHeaderFD): New prototype.
c401cc
* src/util/virfile.c (virFileReadHeaderFD): New function.
c401cc
* src/libvirt_private.syms (virfile.h): Export it.
c401cc
* src/util/virstoragefile.c (virStorageFileGetMetadataInternal)
c401cc
(virStorageFileProbeFormatFromFD): Use it.
c401cc
c401cc
Signed-off-by: Eric Blake <eblake@redhat.com>
c401cc
(cherry picked from commit 5327fad4f292e4f3f84884ffe158c492bf00519c)
c401cc
c401cc
Conflicts:
c401cc
	src/util/virstoragefile.c: buffer signedness
c401cc
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c401cc
---
c401cc
 src/libvirt_private.syms  |  1 +
c401cc
 src/util/virfile.c        | 21 +++++++++++++++++++++
c401cc
 src/util/virfile.h        |  9 ++++++---
c401cc
 src/util/virstoragefile.c | 10 ++--------
c401cc
 4 files changed, 30 insertions(+), 11 deletions(-)
c401cc
c401cc
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
c401cc
index cda024e..852affa 100644
c401cc
--- a/src/libvirt_private.syms
c401cc
+++ b/src/libvirt_private.syms
c401cc
@@ -1401,6 +1401,7 @@ virFileOpenAs;
c401cc
 virFileOpenTty;
c401cc
 virFilePrintf;
c401cc
 virFileReadAll;
c401cc
+virFileReadHeaderFD;
c401cc
 virFileReadLimFD;
c401cc
 virFileResolveAllLinks;
c401cc
 virFileResolveLink;
c401cc
diff --git a/src/util/virfile.c b/src/util/virfile.c
c401cc
index 9b3a4ad..0d4a6be 100644
c401cc
--- a/src/util/virfile.c
c401cc
+++ b/src/util/virfile.c
c401cc
@@ -1153,6 +1153,27 @@ saferead_lim(int fd, size_t max_len, size_t *length)
c401cc
     return NULL;
c401cc
 }
c401cc
 
c401cc
+
c401cc
+/* A wrapper around saferead_lim that merely stops reading at the
c401cc
+ * specified maximum size.  */
c401cc
+int
c401cc
+virFileReadHeaderFD(int fd, int maxlen, char **buf)
c401cc
+{
c401cc
+    size_t len;
c401cc
+    char *s;
c401cc
+
c401cc
+    if (maxlen <= 0) {
c401cc
+        errno = EINVAL;
c401cc
+        return -1;
c401cc
+    }
c401cc
+    s = saferead_lim(fd, maxlen, &len;;
c401cc
+    if (s == NULL)
c401cc
+        return -1;
c401cc
+    *buf = s;
c401cc
+    return len;
c401cc
+}
c401cc
+
c401cc
+
c401cc
 /* A wrapper around saferead_lim that maps a failure due to
c401cc
    exceeding the maximum size limitation to EOVERFLOW.  */
c401cc
 int
c401cc
diff --git a/src/util/virfile.h b/src/util/virfile.h
c401cc
index f6e087e..0d20cdb 100644
c401cc
--- a/src/util/virfile.h
c401cc
+++ b/src/util/virfile.h
c401cc
@@ -122,9 +122,12 @@ int virFileNBDDeviceAssociate(const char *file,
c401cc
 
c401cc
 int virFileDeleteTree(const char *dir);
c401cc
 
c401cc
-int virFileReadLimFD(int fd, int maxlen, char **buf) ATTRIBUTE_RETURN_CHECK;
c401cc
-
c401cc
-int virFileReadAll(const char *path, int maxlen, char **buf) ATTRIBUTE_RETURN_CHECK;
c401cc
+int virFileReadHeaderFD(int fd, int maxlen, char **buf)
c401cc
+    ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(3);
c401cc
+int virFileReadLimFD(int fd, int maxlen, char **buf)
c401cc
+    ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(3);
c401cc
+int virFileReadAll(const char *path, int maxlen, char **buf)
c401cc
+    ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3);
c401cc
 
c401cc
 int virFileWriteStr(const char *path, const char *str, mode_t mode)
c401cc
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
c401cc
diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
c401cc
index 9453599..fc8aa90 100644
c401cc
--- a/src/util/virstoragefile.c
c401cc
+++ b/src/util/virstoragefile.c
c401cc
@@ -788,10 +788,7 @@ virStorageFileGetMetadataInternal(const char *path,
c401cc
         goto cleanup;
c401cc
     }
c401cc
 
c401cc
-    if (VIR_ALLOC_N(buf, len) < 0)
c401cc
-        goto cleanup;
c401cc
-
c401cc
-    if ((len = read(fd, buf, len)) < 0) {
c401cc
+    if ((len = virFileReadHeaderFD(fd, len, (char **)&buf)) < 0) {
c401cc
         virReportSystemError(errno, _("cannot read header '%s'"), path);
c401cc
         goto cleanup;
c401cc
     }
c401cc
@@ -934,15 +931,12 @@ virStorageFileProbeFormatFromFD(const char *path, int fd)
c401cc
         return VIR_STORAGE_FILE_DIR;
c401cc
     }
c401cc
 
c401cc
-    if (VIR_ALLOC_N(head, len) < 0)
c401cc
-        return -1;
c401cc
-
c401cc
     if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
c401cc
         virReportSystemError(errno, _("cannot set to start of '%s'"), path);
c401cc
         goto cleanup;
c401cc
     }
c401cc
 
c401cc
-    if ((len = read(fd, head, len)) < 0) {
c401cc
+    if ((len = virFileReadHeaderFD(fd, len, (char **)&head)) < 0) {
c401cc
         virReportSystemError(errno, _("cannot read header '%s'"), path);
c401cc
         goto cleanup;
c401cc
     }
c401cc
-- 
c401cc
1.9.0
c401cc