summary refs log tree commit diff
diff options
context:
space:
mode:
authorDaniel Verkamp <dverkamp@chromium.org>2019-12-06 10:17:45 +1100
committerCommit Bot <commit-bot@chromium.org>2019-12-10 02:24:14 +0000
commitf21572c7187c8beb9c6bfea6446351ae93200d01 (patch)
tree019623d7ddec73324d741a3b902591c08d77e8fe
parentaa77ea40454c460a7189860f1ea146c45e444dad (diff)
downloadcrosvm-f21572c7187c8beb9c6bfea6446351ae93200d01.tar
crosvm-f21572c7187c8beb9c6bfea6446351ae93200d01.tar.gz
crosvm-f21572c7187c8beb9c6bfea6446351ae93200d01.tar.bz2
crosvm-f21572c7187c8beb9c6bfea6446351ae93200d01.tar.lz
crosvm-f21572c7187c8beb9c6bfea6446351ae93200d01.tar.xz
crosvm-f21572c7187c8beb9c6bfea6446351ae93200d01.tar.zst
crosvm-f21572c7187c8beb9c6bfea6446351ae93200d01.zip
qcow: avoid out-of-bounds access in alloc_refblocks
When all refblocks are consumed, the loop looking for the first free
cluster would access the element at refcounts[refcounts.len()], which is
out of bounds.  Modify the free cluster search loop to check that the
index is in bounds before accessing it.

BUG=chromium:1030751
TEST=qcow_fuzzer

Change-Id: Ib2384b9cf1edeaadb99be5fc67c27a55c03fc6e9
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1953766
Tested-by: Daniel Verkamp <dverkamp@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>
-rw-r--r--qcow/src/qcow.rs7
1 files changed, 5 insertions, 2 deletions
diff --git a/qcow/src/qcow.rs b/qcow/src/qcow.rs
index dd8c1a2..10998f5 100644
--- a/qcow/src/qcow.rs
+++ b/qcow/src/qcow.rs
@@ -742,11 +742,14 @@ impl QcowFile {
             let mut ref_table = vec![0; refcount_table_entries as usize];
             let mut first_free_cluster: u64 = 0;
             for refblock_addr in &mut ref_table {
-                while refcounts[first_free_cluster as usize] != 0 {
-                    first_free_cluster += 1;
+                loop {
                     if first_free_cluster >= refcounts.len() as u64 {
                         return Err(Error::NotEnoughSpaceForRefcounts);
                     }
+                    if refcounts[first_free_cluster as usize] == 0 {
+                        break;
+                    }
+                    first_free_cluster += 1;
                 }
 
                 *refblock_addr = first_free_cluster * cluster_size;