diff mbox

[v4,23/30] zaurus: fix buffer overrun on invalid state load

Message ID 1396275242-10810-24-git-send-email-mst@redhat.com
State New
Headers show

Commit Message

Michael S. Tsirkin March 31, 2014, 2:17 p.m. UTC
CVE-2013-4540

Within scoop_gpio_handler_update, if prev_level has a high bit set, then
we get bit > 16 and that causes a buffer overrun.

Since prev_level comes from wire indirectly, this can
happen on invalid state load.

Similarly for gpio_level and gpio_dir.

To fix, limit to 16 bit.

Reported-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/gpio/zaurus.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

Comments

Dr. David Alan Gilbert April 1, 2014, 11:18 a.m. UTC | #1
* Michael S. Tsirkin (mst@redhat.com) wrote:
> CVE-2013-4540
> 
> Within scoop_gpio_handler_update, if prev_level has a high bit set, then
> we get bit > 16 and that causes a buffer overrun.
> 
> Since prev_level comes from wire indirectly, this can
> happen on invalid state load.
> 
> Similarly for gpio_level and gpio_dir.

Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>

(Without much understanding of the actual, apparently undocumented hardware)

> To fix, limit to 16 bit.
> 
> Reported-by: Michael S. Tsirkin <mst@redhat.com>
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> ---
>  hw/gpio/zaurus.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/hw/gpio/zaurus.c b/hw/gpio/zaurus.c
> index dc79a8b..8e2ce04 100644
> --- a/hw/gpio/zaurus.c
> +++ b/hw/gpio/zaurus.c
> @@ -203,6 +203,15 @@ static bool is_version_0 (void *opaque, int version_id)
>      return version_id == 0;
>  }
>  
> +static bool vmstate_scoop_validate(void *opaque, int version_id)
> +{
> +    ScoopInfo *s = opaque;
> +
> +    return !(s->prev_level & 0xffff0000) &&
> +        !(s->gpio_level & 0xffff0000) &&
> +        !(s->gpio_dir & 0xffff0000);
> +}
> +
>  static const VMStateDescription vmstate_scoop_regs = {
>      .name = "scoop",
>      .version_id = 1,
> @@ -215,6 +224,7 @@ static const VMStateDescription vmstate_scoop_regs = {
>          VMSTATE_UINT32(gpio_level, ScoopInfo),
>          VMSTATE_UINT32(gpio_dir, ScoopInfo),
>          VMSTATE_UINT32(prev_level, ScoopInfo),
> +        VMSTATE_VALIDATE("irq levels are 16 bit", vmstate_scoop_validate),
>          VMSTATE_UINT16(mcr, ScoopInfo),
>          VMSTATE_UINT16(cdr, ScoopInfo),
>          VMSTATE_UINT16(ccr, ScoopInfo),
> -- 
> MST
> 
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
diff mbox

Patch

diff --git a/hw/gpio/zaurus.c b/hw/gpio/zaurus.c
index dc79a8b..8e2ce04 100644
--- a/hw/gpio/zaurus.c
+++ b/hw/gpio/zaurus.c
@@ -203,6 +203,15 @@  static bool is_version_0 (void *opaque, int version_id)
     return version_id == 0;
 }
 
+static bool vmstate_scoop_validate(void *opaque, int version_id)
+{
+    ScoopInfo *s = opaque;
+
+    return !(s->prev_level & 0xffff0000) &&
+        !(s->gpio_level & 0xffff0000) &&
+        !(s->gpio_dir & 0xffff0000);
+}
+
 static const VMStateDescription vmstate_scoop_regs = {
     .name = "scoop",
     .version_id = 1,
@@ -215,6 +224,7 @@  static const VMStateDescription vmstate_scoop_regs = {
         VMSTATE_UINT32(gpio_level, ScoopInfo),
         VMSTATE_UINT32(gpio_dir, ScoopInfo),
         VMSTATE_UINT32(prev_level, ScoopInfo),
+        VMSTATE_VALIDATE("irq levels are 16 bit", vmstate_scoop_validate),
         VMSTATE_UINT16(mcr, ScoopInfo),
         VMSTATE_UINT16(cdr, ScoopInfo),
         VMSTATE_UINT16(ccr, ScoopInfo),