qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] buffer overruns in qemu-system-sparc (hw/eccmemctl.c: ecc_r


From: Julian Seward
Subject: [Qemu-devel] buffer overruns in qemu-system-sparc (hw/eccmemctl.c: ecc_reset())
Date: Tue, 17 Jun 2008 22:35:19 +0200
User-agent: KMail/1.9.5

This is in qemu svn trunk.

Running 'qemu-system-sparc -M SS-10' (or SS-20) produces a bunch of
invalid writes in hw/eccmemctl.c: ecc_reset(), as shown at the end
of this message.  Sometimes these are sufficiently severe to corrupt
the heap and cause glibc to abort qemu.  Problem does not happen with
-M SS-5.

The writes are caused by

290:    s->regs[ECC_VCR] = 0;
291:    s->regs[ECC_MFAR0] = 0x07c00000;
292:    s->regs[ECC_MFAR1] = 0;

In fact all the assignments to s->regs[] are very strange.  regs[]
is declared with 9 elements:

  #define ECC_NREGS      9
  ...
  uint32_t regs[ECC_NREGS];

so valid indices should be 0 .. 8.  But the constants ECC_* used to
index in ..

/* Register offsets */
#define ECC_MER        0                /* Memory Enable Register */
#define ECC_MDR        4                /* Memory Delay Register */
#define ECC_MFSR       8                /* Memory Fault Status Register */
#define ECC_VCR        12               /* Video Configuration Register */
#define ECC_MFAR0      16               /* Memory Fault Address Register 0 */
#define ECC_MFAR1      20               /* Memory Fault Address Register 1 */
#define ECC_DR         24               /* Diagnostic Register */
#define ECC_ECR0       28               /* Event Count Register 0 */
#define ECC_ECR1       32               /* Event Count Register 1 */

are register offsets, not indexes; AFAICS they should be divided by
sizeof(uint32_t) before use.

Even stranger .. at eccmemctl.c:297, having (incorrectly) filled in 
s->regs[], there is a loop that zeroes all but one of the entries:

    for (i = 1; i < ECC_NREGS; i++)
        s->regs[i] = 0;

The following kludge removes the invalid writes, but is not elegant,
and still leaves the question of why the loop zeroes out the entries
afterwards.

J

Index: hw/eccmemctl.c
===================================================================
--- hw/eccmemctl.c      (revision 4744)
+++ hw/eccmemctl.c      (working copy)
@@ -281,18 +281,18 @@
 static void ecc_reset(void *opaque)
 {
     ECCState *s = opaque;
-    int i;
+    int i, four = sizeof(s->regs[0]);

-    s->regs[ECC_MER] &= (ECC_MER_VER | ECC_MER_IMPL);
-    s->regs[ECC_MER] |= ECC_MER_MRR;
-    s->regs[ECC_MDR] = 0x20;
-    s->regs[ECC_MFSR] = 0;
-    s->regs[ECC_VCR] = 0;
-    s->regs[ECC_MFAR0] = 0x07c00000;
-    s->regs[ECC_MFAR1] = 0;
-    s->regs[ECC_DR] = 0;
-    s->regs[ECC_ECR0] = 0;
-    s->regs[ECC_ECR1] = 0;
+    s->regs[ECC_MER   / four] &= (ECC_MER_VER | ECC_MER_IMPL);
+    s->regs[ECC_MER   / four] |= ECC_MER_MRR;
+    s->regs[ECC_MDR   / four] = 0x20;
+    s->regs[ECC_MFSR  / four] = 0;
+    s->regs[ECC_VCR   / four] = 0;
+    s->regs[ECC_MFAR0 / four] = 0x07c00000;
+    s->regs[ECC_MFAR1 / four] = 0;
+    s->regs[ECC_DR    / four] = 0;
+    s->regs[ECC_ECR0  / four] = 0;
+    s->regs[ECC_ECR1  / four] = 0;

     for (i = 1; i < ECC_NREGS; i++)
         s->regs[i] = 0;


The original problem:

==21509== Invalid write of size 4
==21509==    at 0x42E056: ecc_reset (eccmemctl.c:290)
==21509==    by 0x42E149: ecc_init (eccmemctl.c:323)
==21509==    by 0x425E7F: sun4m_hw_init (sun4m.c:547)
==21509==    by 0x40D50E: main (vl.c:8609)
==21509==  Address 0x7af3c20 is 8 bytes after a block of size 48 alloc'd
==21509==    at 0x4C234BB: malloc (vg_replace_malloc.c:207)
==21509==    by 0x42F995: qemu_mallocz (qemu-malloc.c:44)
==21509==    by 0x42E0DA: ecc_init (eccmemctl.c:306)
==21509==    by 0x425E7F: sun4m_hw_init (sun4m.c:547)
==21509==    by 0x40D50E: main (vl.c:8609)
==21509==
==21509== Invalid write of size 4
==21509==    at 0x42E05D: ecc_reset (eccmemctl.c:291)
==21509==    by 0x42E149: ecc_init (eccmemctl.c:323)
==21509==    by 0x425E7F: sun4m_hw_init (sun4m.c:547)
==21509==    by 0x40D50E: main (vl.c:8609)
==21509==  Address 0x7af3c30 is not stack'd, malloc'd or (recently) free'd
==21509==
==21509== Invalid write of size 4
==21509==    at 0x42E064: ecc_reset (eccmemctl.c:292)
==21509==    by 0x42E149: ecc_init (eccmemctl.c:323)
==21509==    by 0x425E7F: sun4m_hw_init (sun4m.c:547)
==21509==    by 0x40D50E: main (vl.c:8609)
==21509==  Address 0x7af3c40 is 8 bytes before a block of size 296 alloc'd
==21509==    at 0x4C234BB: malloc (vg_replace_malloc.c:207)
==21509==    by 0x40973E: register_savevm (vl.c:5958)
==21509==    by 0x42E134: ecc_init (eccmemctl.c:321)
==21509==    by 0x425E7F: sun4m_hw_init (sun4m.c:547)
==21509==    by 0x40D50E: main (vl.c:8609)




reply via email to

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