From 8cfc832cf6771c950c9220b6fe8c9df82f577c52 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 25 Apr 2024 17:52:05 -0400 Subject: [PATCH] libextr2fs: handle short reads/writes while creating the qcow file This issue was flagged by Coverity, although its analysis was incorrect. This isn't actually a memory overrun / security issue, but rather a functional correctness issue since POSIX allows reads and writes to be partially completed, and in those cases qcow2_copy_data() could result in a corrutped qcow2 file. Addresses-Coverity-Bug: 1531830 Signed-off-by: Theodore Ts'o --- lib/ext2fs/qcow2.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/lib/ext2fs/qcow2.c b/lib/ext2fs/qcow2.c index 2082417..8f96eee 100644 --- a/lib/ext2fs/qcow2.c +++ b/lib/ext2fs/qcow2.c @@ -134,7 +134,9 @@ static int qcow2_read_l2_table(struct ext2_qcow2_image *img, static int qcow2_copy_data(int fdin, int fdout, __u64 off_in, __u64 off_out, void *buf, size_t count) { - size_t size; + ssize_t c1, c2, c; + void *ptr; + int retries = 10; assert(buf); @@ -144,14 +146,24 @@ static int qcow2_copy_data(int fdin, int fdout, __u64 off_in, if (ext2fs_llseek(fdin, off_in, SEEK_SET) < 0) return errno; - size = read(fdin, buf, count); - if (size != count) - return errno; - - size = write(fdout, buf, count); - if (size != count) - return errno; - + while (count > 0) { + errno = 0; + c1 = read(fdin, buf, count); + if (c1 < 0 || ((c1 == 0) && errno)) + return errno; + if (c1 == 0) + break; /* EOF */ + + for (ptr = buf, c = c1; c > 0; ptr += c2, c -= c2) { + errno = 0; + c2 = write(fdout, ptr, c1); + if (c2 < 0 || ((c2 == 0) && errno)) + return errno; + if (c2 == 0 && --retries <= 0) + break; /* This should never happen... */ + } + count -= c1; + } return 0; } -- 1.8.3.1