1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2024-12-23 03:53:43 +01:00

Bad pointer validation for 32 bit x86.

This corresponds to commit 649f1fb344.

Signed-off-by: Paul Pluzhnikov <ppluzhnikov@google.com>
This commit is contained in:
Arun Sharma 2009-03-16 11:06:26 -07:00
parent 5822fca27a
commit ff0ae70cc3
6 changed files with 80 additions and 10 deletions

View file

@ -65,8 +65,17 @@ struct cursor
}
sigcontext_format;
unw_word_t sigcontext_addr;
int validate;
ucontext_t *uc;
};
static inline ucontext_t *
dwarf_get_uc(const struct dwarf_cursor *cursor)
{
const struct cursor *c = (struct cursor *) cursor->as_arg;
return c->uc;
}
#define DWARF_GET_LOC(l) ((l).val)
#ifdef UNW_LOCAL_ONLY
@ -75,10 +84,10 @@ struct cursor
# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) })
# define DWARF_IS_REG_LOC(l) 0
# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) \
tdep_uc_addr((c)->as_arg, (r)), 0))
tdep_uc_addr(dwarf_get_uc(c), (r)), 0))
# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0)
# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) \
tdep_uc_addr((c)->as_arg, (r)), 0))
tdep_uc_addr(dwarf_get_uc(c), (r)), 0))
static inline int
dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val)
@ -103,8 +112,8 @@ dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val)
{
if (!DWARF_GET_LOC (loc))
return -1;
*val = *(unw_word_t *) DWARF_GET_LOC (loc);
return 0;
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val,
0, c->as_arg);
}
static inline int
@ -112,8 +121,8 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
{
if (!DWARF_GET_LOC (loc))
return -1;
*(unw_word_t *) DWARF_GET_LOC (loc) = val;
return 0;
return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val,
1, c->as_arg);
}
#else /* !UNW_LOCAL_ONLY */

View file

@ -102,6 +102,47 @@ get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr,
return 0;
}
#define PAGE_SIZE 4096
#define PAGE_START(a) ((a) & ~(PAGE_SIZE-1))
/* Cache of already validated addresses */
#define NLGA 4
static unw_word_t last_good_addr[NLGA];
static int lga_victim;
static int
validate_mem (unw_word_t addr)
{
int i, victim;
addr = PAGE_START(addr);
for (i = 0; i < NLGA; i++)
{
if (last_good_addr[i] && (addr == last_good_addr[i]))
return 0;
}
if (msync ((void *) addr, 1, MS_SYNC) == -1)
return -1;
victim = lga_victim;
for (i = 0; i < NLGA; i++) {
if (!last_good_addr[victim]) {
last_good_addr[victim++] = addr;
return 0;
}
victim = (victim + 1) % NLGA;
}
/* All slots full. Evict the victim. */
last_good_addr[victim] = addr;
victim = (victim + 1) % NLGA;
lga_victim = victim;
return 0;
}
static int
access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
void *arg)
@ -113,6 +154,10 @@ access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write,
}
else
{
/* validate address */
const struct cursor *c = (const struct cursor *)arg;
if (c && c->validate && validate_mem(addr))
return -1;
*val = *(unw_word_t *) addr;
Debug (16, "mem[%x] -> %x\n", addr, *val);
}
@ -124,7 +169,7 @@ access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write,
void *arg)
{
unw_word_t *addr;
ucontext_t *uc = arg;
ucontext_t *uc = ((struct cursor *)arg)->uc;
if (unw_is_fpreg (reg))
goto badreg;
@ -153,7 +198,7 @@ static int
access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
int write, void *arg)
{
ucontext_t *uc = arg;
ucontext_t *uc = ((struct cursor *)arg)->uc;
unw_fpreg_t *addr;
if (!unw_is_fpreg (reg))

View file

@ -47,7 +47,9 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc)
Debug (1, "(cursor=%p)\n", c);
c->dwarf.as = unw_local_addr_space;
c->dwarf.as_arg = uc;
c->dwarf.as_arg = c;
c->uc = uc;
c->validate = 0;
return common_init (c);
}

View file

@ -41,6 +41,16 @@ unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg)
c->dwarf.as = as;
c->dwarf.as_arg = as_arg;
if (as == unw_local_addr_space)
{
c->dwarf.as_arg = c;
c->uc = as_arg;
}
else
{
c->dwarf.as_arg = as_arg;
c->uc = 0;
}
return common_init (c);
#endif /* !UNW_LOCAL_ONLY */
}

View file

@ -34,7 +34,7 @@ x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
{
#if defined(__linux)
struct cursor *c = (struct cursor *) cursor;
ucontext_t *uc = c->dwarf.as_arg;
ucontext_t *uc = c->uc;
/* Ensure c->pi is up-to-date. On x86, it's relatively common to be
missing DWARF unwind info. We don't want to fail in that case,

View file

@ -49,6 +49,10 @@ unw_step (unw_cursor_t *cursor)
or skip over the signal trampoline. */
struct dwarf_loc ebp_loc, eip_loc;
/* We could get here because of missing/bad unwind information.
Validate all addresses before dereferencing. */
c->validate = 1;
Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret);
if (unw_is_signal_frame (cursor))