File d697b0f3-storage-avoid-short-reads.patch of Package libvirt.openSUSE_13.1_Update

From d697b0f383a23a94d7415b0e02b025eda46ad534 Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Tue, 5 Nov 2013 10:30:56 -0700
Subject: [PATCH] storage: avoid short reads while chasing backing chain

Our backing file chain code was not very robust to an ill-timed
EINTR, which could lead to a short read causing us to randomly
treat metadata differently than usual.  But the existing
virFileReadLimFD forces an error if we don't read the entire
file, even though we only care about the header of the file.
So add a new virFile function that does what we want.

* src/util/virfile.h (virFileReadHeaderFD): New prototype.
* src/util/virfile.c (virFileReadHeaderFD): New function.
* src/libvirt_private.syms (virfile.h): Export it.
* src/util/virstoragefile.c (virStorageFileGetMetadataInternal)
(virStorageFileProbeFormatFromFD): Use it.

Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit 5327fad4f292e4f3f84884ffe158c492bf00519c)

Conflicts:
	src/util/virstoragefile.c: buffer signedness
---
 src/libvirt_private.syms  |  1 +
 src/util/virfile.c        | 21 +++++++++++++++++++++
 src/util/virfile.h        |  9 ++++++---
 src/util/virstoragefile.c | 10 ++--------
 4 files changed, 30 insertions(+), 11 deletions(-)

Index: libvirt-1.1.2/src/libvirt_private.syms
===================================================================
--- libvirt-1.1.2.orig/src/libvirt_private.syms
+++ libvirt-1.1.2/src/libvirt_private.syms
@@ -1386,6 +1386,7 @@ virFileOpenAs;
 virFileOpenTty;
 virFilePrintf;
 virFileReadAll;
+virFileReadHeaderFD;
 virFileReadLimFD;
 virFileResolveAllLinks;
 virFileResolveLink;
Index: libvirt-1.1.2/src/util/virfile.c
===================================================================
--- libvirt-1.1.2.orig/src/util/virfile.c
+++ libvirt-1.1.2/src/util/virfile.c
@@ -1153,6 +1153,27 @@ saferead_lim(int fd, size_t max_len, siz
     return NULL;
 }
 
+
+/* A wrapper around saferead_lim that merely stops reading at the
+ * specified maximum size.  */
+int
+virFileReadHeaderFD(int fd, int maxlen, char **buf)
+{
+    size_t len;
+    char *s;
+
+    if (maxlen <= 0) {
+        errno = EINVAL;
+        return -1;
+    }
+    s = saferead_lim(fd, maxlen, &len);
+    if (s == NULL)
+        return -1;
+    *buf = s;
+    return len;
+}
+
+
 /* A wrapper around saferead_lim that maps a failure due to
    exceeding the maximum size limitation to EOVERFLOW.  */
 int
Index: libvirt-1.1.2/src/util/virfile.h
===================================================================
--- libvirt-1.1.2.orig/src/util/virfile.h
+++ libvirt-1.1.2/src/util/virfile.h
@@ -122,9 +122,12 @@ int virFileNBDDeviceAssociate(const char
 
 int virFileDeleteTree(const char *dir);
 
-int virFileReadLimFD(int fd, int maxlen, char **buf) ATTRIBUTE_RETURN_CHECK;
-
-int virFileReadAll(const char *path, int maxlen, char **buf) ATTRIBUTE_RETURN_CHECK;
+int virFileReadHeaderFD(int fd, int maxlen, char **buf)
+    ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(3);
+int virFileReadLimFD(int fd, int maxlen, char **buf)
+    ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(3);
+int virFileReadAll(const char *path, int maxlen, char **buf)
+    ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3);
 
 int virFileWriteStr(const char *path, const char *str, mode_t mode)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
Index: libvirt-1.1.2/src/util/virstoragefile.c
===================================================================
--- libvirt-1.1.2.orig/src/util/virstoragefile.c
+++ libvirt-1.1.2/src/util/virstoragefile.c
@@ -788,10 +788,7 @@ virStorageFileGetMetadataInternal(const
         goto cleanup;
     }
 
-    if (VIR_ALLOC_N(buf, len) < 0)
-        goto cleanup;
-
-    if ((len = read(fd, buf, len)) < 0) {
+    if ((len = virFileReadHeaderFD(fd, len, (char **)&buf)) < 0) {
         virReportSystemError(errno, _("cannot read header '%s'"), path);
         goto cleanup;
     }
@@ -934,15 +931,12 @@ virStorageFileProbeFormatFromFD(const ch
         return VIR_STORAGE_FILE_DIR;
     }
 
-    if (VIR_ALLOC_N(head, len) < 0)
-        return -1;
-
     if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
         virReportSystemError(errno, _("cannot set to start of '%s'"), path);
         goto cleanup;
     }
 
-    if ((len = read(fd, head, len)) < 0) {
+    if ((len = virFileReadHeaderFD(fd, len, (char **)&head)) < 0) {
         virReportSystemError(errno, _("cannot read header '%s'"), path);
         goto cleanup;
     }
openSUSE Build Service is sponsored by