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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).