|
|
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 |
|