From: Julian Seward <jseward@acm.org>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] buffer overruns in qemu-system-sparc (hw/eccmemctl.c: ecc_reset())
Date: Tue, 17 Jun 2008 22:35:19 +0200 [thread overview]
Message-ID: <200806172235.19974.jseward@acm.org> (raw)
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)
next reply other threads:[~2008-06-17 20:42 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-06-17 20:35 Julian Seward [this message]
2008-06-17 23:37 ` [Qemu-devel] buffer overruns in qemu-system-sparc (hw/eccmemctl.c: ecc_reset()) Paul Brook
2008-06-17 23:38 ` Robert Reif
2008-06-17 23:58 ` Julian Seward
2008-06-19 14:11 ` Blue Swirl
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200806172235.19974.jseward@acm.org \
--to=jseward@acm.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.