qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v4 15/30] stellaris_enet: avoid buffer orerrun o


From: Dr. David Alan Gilbert
Subject: Re: [Qemu-devel] [PATCH v4 15/30] stellaris_enet: avoid buffer orerrun on incoming migration (part 3)
Date: Tue, 1 Apr 2014 10:51:54 +0100
User-agent: Mutt/1.5.21 (2010-09-15)

* Michael S. Tsirkin (address@hidden) wrote:
> CVE-2013-4532
> 
> s->tx_frame_len is read from the wire and can later used as an index
> into s->tx_fifo[] for memset() when a DATA command is issued by the guest.
> 
> In this case s->tx_frame_len is checked to avoid an overrun, but if the
> value is negative a subsequently executed guest can underrun the buffer
> with zeros via the memset() call.
> 
> Additionally, tx_frame_len is used to validate that tx_fifo_len
> doesn't exceed the fifo bounds - the assumption being that data model
> never makes it exceed 2032.
> 
> Fix this by failing migration if the incoming value of s->tx_frame_len
> is less than -1 (the emulation code allows from -1 as a special case)
> or if it exceeds 2032.
> 
> Reported-by: Michael Roth <address@hidden>
> Reported-by: Peter Maydell <address@hidden>
> Signed-off-by: Michael S. Tsirkin <address@hidden>
> ---
>  hw/net/stellaris_enet.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c
> index aed00fd..90ff950 100644
> --- a/hw/net/stellaris_enet.c
> +++ b/hw/net/stellaris_enet.c
> @@ -373,7 +373,11 @@ static int stellaris_enet_load(QEMUFile *f, void 
> *opaque, int version_id)
>      s->mtxd = qemu_get_be32(f);
>      s->mrxd = qemu_get_be32(f);
>      s->np = qemu_get_be32(f);
> -    s->tx_frame_len = qemu_get_be32(f);
> +    v = qemu_get_be32(f);
> +    if (v < -1 || s->tx_frame_len > 2032) {
> +        return -EINVAL;
> +    }
> +    s->tx_frame_len = v;

I think that's wrong; 'stellaris_enet_write' does the following:

            s->tx_frame_len = value & 0xffff;
            if (s->tx_frame_len > 2032) {
                DPRINTF("TX frame too long (%d)\n", s->tx_frame_len);
                s->tx_frame_len = 0;
                s->ris |= SE_INT_TXER;
                stellaris_enet_update(s);
            } else {
                DPRINTF("Start TX frame len=%d\n", s->tx_frame_len);
                /* The value written does not include the ethernet header.  */
                s->tx_frame_len += 14;
                if ((s->tctl & SE_TCTL_CRC) == 0)
                    s->tx_frame_len += 4;

So lets say that tx_frame_len is initially 2032 when written; 14 is added to it
at this point, and if the CRC flag is set then another 4.   Thus it seems a user
can set the value in tx_frame_len to 2032+14+4=2050  - which is a bit worrying
given the buffer is only 2048 bytes.

Dave

>      v = qemu_get_be32(f);
>      /* How many bytes does data use in tx fifo. */
>      sz = s->tx_frame_len == -1 ? 2 : 4;
> -- 
> MST
> 
--
Dr. David Alan Gilbert / address@hidden / Manchester, UK



reply via email to

[Prev in Thread] Current Thread [Next in Thread]