Patchwork qcow2: Fix access after end of array

login
register
mail settings
Submitter Kevin Wolf
Date Feb. 16, 2010, 2:54 p.m.
Message ID <1266332089-14381-1-git-send-email-kwolf@redhat.com>
Download mbox | patch
Permalink /patch/45505/
State New
Headers show

Comments

Kevin Wolf - Feb. 16, 2010, 2:54 p.m.
If a write requests crosses a L2 table boundary and all clusters until the
end of the L2 table are usable for the request, we must not look at the next
L2 entry because we already have arrived at the end of the array.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/qcow2-cluster.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)
Anthony Liguori - Feb. 19, 2010, 10:01 p.m.
On 02/16/2010 08:54 AM, Kevin Wolf wrote:
> If a write requests crosses a L2 table boundary and all clusters until the
> end of the L2 table are usable for the request, we must not look at the next
> L2 entry because we already have arrived at the end of the array.
>
> Signed-off-by: Kevin Wolf<kwolf@redhat.com>
>    

Applied.  Thanks.

Regards,

Anthony Liguori
> ---
>   block/qcow2-cluster.c |    8 ++++++--
>   1 files changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
> index 3501a94..b13b693 100644
> --- a/block/qcow2-cluster.c
> +++ b/block/qcow2-cluster.c
> @@ -750,12 +750,15 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
>       while (i<  nb_clusters) {
>           i += count_contiguous_clusters(nb_clusters - i, s->cluster_size,
>                   &l2_table[l2_index], i, 0);
> -
> -        if(be64_to_cpu(l2_table[l2_index + i]))
> +        if ((i>= nb_clusters) || be64_to_cpu(l2_table[l2_index + i])) {
>               break;
> +        }
>
>           i += count_contiguous_free_clusters(nb_clusters - i,
>                   &l2_table[l2_index + i]);
> +        if (i>= nb_clusters) {
> +            break;
> +        }
>
>           cluster_offset = be64_to_cpu(l2_table[l2_index + i]);
>
> @@ -763,6 +766,7 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
>                   (cluster_offset&  QCOW_OFLAG_COMPRESSED))
>               break;
>       }
> +    assert(i<= nb_clusters);
>       nb_clusters = i;
>
>       /*
>

Patch

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 3501a94..b13b693 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -750,12 +750,15 @@  int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
     while (i < nb_clusters) {
         i += count_contiguous_clusters(nb_clusters - i, s->cluster_size,
                 &l2_table[l2_index], i, 0);
-
-        if(be64_to_cpu(l2_table[l2_index + i]))
+        if ((i >= nb_clusters) || be64_to_cpu(l2_table[l2_index + i])) {
             break;
+        }
 
         i += count_contiguous_free_clusters(nb_clusters - i,
                 &l2_table[l2_index + i]);
+        if (i >= nb_clusters) {
+            break;
+        }
 
         cluster_offset = be64_to_cpu(l2_table[l2_index + i]);
 
@@ -763,6 +766,7 @@  int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
                 (cluster_offset & QCOW_OFLAG_COMPRESSED))
             break;
     }
+    assert(i <= nb_clusters);
     nb_clusters = i;
 
     /*