summaryrefslogtreecommitdiffstats
path: root/daemon/initrd.c
diff options
context:
space:
mode:
authorRichard Jones <rjones@redhat.com>2010-05-07 13:30:42 +0100
committerRichard Jones <rjones@redhat.com>2010-05-07 15:27:29 +0100
commit42f59b28f123f53ae038df23a9abee08e959e46b (patch)
tree4ac2c3ac492680659fffde3b4316703c74953bcd /daemon/initrd.c
parenta84f1360499309e2d2ecb661adc6917539b5eef4 (diff)
downloadlibguestfs-42f59b28f123f53ae038df23a9abee08e959e46b.tar.gz
libguestfs-42f59b28f123f53ae038df23a9abee08e959e46b.tar.xz
libguestfs-42f59b28f123f53ae038df23a9abee08e959e46b.zip
daemon: Fix read-file so it fails gracefully for large files (RHBZ#589039).
Pengzhen Cao noticed that read-file would fail for files larger than the protocol size; this is *not* the bug. However it would also lose protocol synchronization after this. The reason was that functions which return RBufferOut in the generator must not 'touch' the *size_r parameter along error return paths. I fixed read-file and initrd-cat, and I checked that pread was doing the right thing. This also adds regression tests for read-file with various categories of large file.
Diffstat (limited to 'daemon/initrd.c')
-rw-r--r--daemon/initrd.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/daemon/initrd.c b/daemon/initrd.c
index addeb144..932564b8 100644
--- a/daemon/initrd.c
+++ b/daemon/initrd.c
@@ -142,25 +142,24 @@ do_initrd_cat (const char *path, const char *filename, size_t *size_r)
goto cleanup;
}
- *size_r = statbuf.st_size;
/* The actual limit on messages is smaller than this. This
* check just limits the amount of memory we'll try and allocate
* here. If the message is larger than the real limit, that will
* be caught later when we try to serialize the message.
*/
- if (*size_r >= GUESTFS_MESSAGE_MAX) {
+ if (statbuf.st_size >= GUESTFS_MESSAGE_MAX) {
reply_with_error ("%s:%s: file is too large for the protocol",
path, filename);
goto cleanup;
}
- ret = malloc (*size_r);
+ ret = malloc (statbuf.st_size);
if (ret == NULL) {
reply_with_perror ("malloc");
goto cleanup;
}
- if (xread (fd, ret, *size_r) == -1) {
+ if (xread (fd, ret, statbuf.st_size) == -1) {
reply_with_perror ("read: %s:%s", path, filename);
free (ret);
ret = NULL;
@@ -175,6 +174,11 @@ do_initrd_cat (const char *path, const char *filename, size_t *size_r)
}
fd = -1;
+ /* Mustn't touch *size_r until we are sure that we won't return any
+ * error (RHBZ#589039).
+ */
+ *size_r = statbuf.st_size;
+
cleanup:
if (fd >= 0)
close (fd);