diff mbox

[02/18] linux-user: Fix the load of ELF files that have no "useful" symbol

Message ID 8a89625471221eac9e59330f03fa6bb2d3154ea5.1308583801.git.riku.voipio@iki.fi
State New
Headers show

Commit Message

Riku Voipio June 20, 2011, 4:20 p.m. UTC
From: Cédric VINCENT <cedric.vincent@st.com>

This patch fixes a "double free()" due to "realloc(syms, 0)" in the
loader when the ELF file has no "useful" symbol, as with the following
example (compiled with "sh4-linux-gcc -nostdlib"):

    .text
    .align 1
    .global _start
    _start:
        mov     #1, r3
        trapa   #40     // syscall(__NR_exit)
        nop

The bug appears when the log (option "-d") is enabled.

Signed-off-by: Cédric VINCENT <cedric.vincent@st.com>
Signed-off-by: Yves JANIN <yves.janin@st.com>
Signed-off-by: Riku Voipio <riku.voipio@iki.fi>
---
 linux-user/elfload.c |   34 +++++++++++++++++++---------------
 1 files changed, 19 insertions(+), 15 deletions(-)

Comments

vincent June 21, 2011, 7:07 a.m. UTC | #1
On Mon, Jun 20, 2011 at 06:20:07PM +0200, riku.voipio@iki.fi wrote:
> 
> Signed-off-by: Cédric VINCENT <cedric.vincent@st.com>
> Signed-off-by: Yves JANIN <yves.janin@st.com>
> Signed-off-by: Riku Voipio <riku.voipio@iki.fi>

The tag "Reviewed-by: Richard Henderson <rth@twiddle.net>" is missing:

    http://lists.gnu.org/archive/html/qemu-devel/2011-06/msg00075.html
diff mbox

Patch

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index dcfeb7a..a4aabd5 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1643,9 +1643,9 @@  static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
 {
     int i, shnum, nsyms, sym_idx = 0, str_idx = 0;
     struct elf_shdr *shdr;
-    char *strings;
-    struct syminfo *s;
-    struct elf_sym *syms, *new_syms;
+    char *strings = NULL;
+    struct syminfo *s = NULL;
+    struct elf_sym *new_syms, *syms = NULL;
 
     shnum = hdr->e_shnum;
     i = shnum * sizeof(struct elf_shdr);
@@ -1670,24 +1670,19 @@  static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
     /* Now know where the strtab and symtab are.  Snarf them.  */
     s = malloc(sizeof(*s));
     if (!s) {
-        return;
+        goto give_up;
     }
 
     i = shdr[str_idx].sh_size;
     s->disas_strtab = strings = malloc(i);
     if (!strings || pread(fd, strings, i, shdr[str_idx].sh_offset) != i) {
-        free(s);
-        free(strings);
-        return;
+        goto give_up;
     }
 
     i = shdr[sym_idx].sh_size;
     syms = malloc(i);
     if (!syms || pread(fd, syms, i, shdr[sym_idx].sh_offset) != i) {
-        free(s);
-        free(strings);
-        free(syms);
-        return;
+        goto give_up;
     }
 
     nsyms = i / sizeof(struct elf_sym);
@@ -1710,16 +1705,18 @@  static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
         }
     }
 
+    /* No "useful" symbol.  */
+    if (nsyms == 0) {
+        goto give_up;
+    }
+
     /* Attempt to free the storage associated with the local symbols
        that we threw away.  Whether or not this has any effect on the
        memory allocation depends on the malloc implementation and how
        many symbols we managed to discard.  */
     new_syms = realloc(syms, nsyms * sizeof(*syms));
     if (new_syms == NULL) {
-        free(s);
-        free(syms);
-        free(strings);
-        return;
+        goto give_up;
     }
     syms = new_syms;
 
@@ -1734,6 +1731,13 @@  static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
     s->lookup_symbol = lookup_symbolxx;
     s->next = syminfos;
     syminfos = s;
+
+    return;
+
+give_up:
+    free(s);
+    free(strings);
+    free(syms);
 }
 
 int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,