diff options
author | Mark Wielaard <mjw@redhat.com> | 2009-10-20 13:55:15 +0200 |
---|---|---|
committer | Mark Wielaard <mjw@redhat.com> | 2009-10-20 13:55:15 +0200 |
commit | bf043a5f9c9f807d670276b6c389bf5439245edb (patch) | |
tree | 907ecfaaa99d2a2c5bce7293ad7d992de44e806a | |
parent | c42e2d2e1a9e8c09a435089ce351e1d36309dd9b (diff) | |
download | systemtap-steved-bf043a5f9c9f807d670276b6c389bf5439245edb.tar.gz systemtap-steved-bf043a5f9c9f807d670276b6c389bf5439245edb.tar.xz systemtap-steved-bf043a5f9c9f807d670276b6c389bf5439245edb.zip |
Be paranoid about table size resolving cie_for_fde and fde_pointer_type.
* runtime/unwind.c (cie_for_fde): Take table and table_len into account.
(fde_pointer_type): Likewise.
* runtime/unwind/unwind.h: Adjust function prototypes.
-rw-r--r-- | runtime/unwind.c | 25 | ||||
-rw-r--r-- | runtime/unwind/unwind.h | 6 |
2 files changed, 22 insertions, 9 deletions
diff --git a/runtime/unwind.c b/runtime/unwind.c index 00108a39..0b4e6a9e 100644 --- a/runtime/unwind.c +++ b/runtime/unwind.c @@ -88,7 +88,7 @@ static sleb128_t get_sleb128(const u8 **pcur, const u8 *end) /* given an FDE, find its CIE */ static const u32 *cie_for_fde(const u32 *fde, void *unwind_data, - int is_ehframe) + uint32_t table_len, int is_ehframe) { const u32 *cie; @@ -118,6 +118,11 @@ static const u32 *cie_for_fde(const u32 *fde, void *unwind_data, else cie = unwind_data + fde[1]; + /* Make sure address falls in the table */ + if (((void *)cie) < ((void*)unwind_data) + || ((void*)cie) > ((void*)(unwind_data + table_len))) + return NULL; + if (*cie <= sizeof(*cie) + 4 || *cie >= fde[1] - sizeof(*fde) || (*cie & (sizeof(*cie) - 1)) || (cie[1] != 0xffffffff && cie[1] != 0)) { @@ -200,7 +205,8 @@ static unsigned long read_pointer(const u8 **pLoc, const void *end, signed ptrTy return value; } -static signed fde_pointer_type(const u32 *cie) +static signed fde_pointer_type(const u32 *cie, void *unwind_data, + uint32_t table_len) { const u8 *ptr = (const u8 *)(cie + 2); unsigned version = *ptr; @@ -212,11 +218,16 @@ static signed fde_pointer_type(const u32 *cie) const u8 *end = (const u8 *)(cie + 1) + *cie; uleb128_t len; + /* end of cie should fall within unwind table. */ + if (((void*)end) < ((void *)unwind_data) + || ((void *)end) > ((void *)(unwind_data + table_len))) + return -1; + /* check if augmentation size is first (and thus present) */ if (*ptr != 'z') return -1; /* check if augmentation string is nul-terminated */ - if ((ptr = memchr(aug = (const void *)ptr, 0, end - ptr)) == NULL) + if ((ptr = memchr(aug = (const void *)ptr, 0, end - ptr)) == NULL) return -1; ++ptr; /* skip terminator */ get_uleb128(&ptr, end); /* skip code alignment */ @@ -606,10 +617,10 @@ static int unwind_frame(struct unwind_frame_info *frame, /* found the fde, now set startLoc and endLoc */ if (fde != NULL) { - cie = cie_for_fde(fde, table, is_ehframe); + cie = cie_for_fde(fde, table, table_len, is_ehframe); if (likely(cie != NULL && cie != &bad_cie && cie != ¬_fde)) { ptr = (const u8 *)(fde + 2); - ptrType = fde_pointer_type(cie); + ptrType = fde_pointer_type(cie, table, table_len); startLoc = read_pointer(&ptr, (const u8 *)(fde + 1) + *fde, ptrType); startLoc = adjustStartLoc(startLoc, m, s, ptrType, is_ehframe); @@ -632,12 +643,12 @@ static int unwind_frame(struct unwind_frame_info *frame, for (fde = table, tableSize = table_len; cie = NULL, tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde; tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) { dbug_unwind(3, "fde=%lx tableSize=%d\n", (long)*fde, (int)tableSize); - cie = cie_for_fde(fde, table, is_ehframe); + cie = cie_for_fde(fde, table, table_len, is_ehframe); if (cie == &bad_cie) { cie = NULL; break; } - if (cie == NULL || cie == ¬_fde || (ptrType = fde_pointer_type(cie)) < 0) + if (cie == NULL || cie == ¬_fde || (ptrType = fde_pointer_type(cie, table, table_len)) < 0) continue; ptr = (const u8 *)(fde + 2); diff --git a/runtime/unwind/unwind.h b/runtime/unwind/unwind.h index 285a3a34..023ea603 100644 --- a/runtime/unwind/unwind.h +++ b/runtime/unwind/unwind.h @@ -143,8 +143,10 @@ static unsigned long read_pointer(const u8 **pLoc, const void *end, signed ptrType); static const u32 bad_cie, not_fde; -static const u32 *cie_for_fde(const u32 *fde, void *table, int is_ehframe); -static signed fde_pointer_type(const u32 *cie); +static const u32 *cie_for_fde(const u32 *fde, void *table, + uint32_t table_len, int is_ehframe); +static signed fde_pointer_type(const u32 *cie, + void *table, uint32_t table_len); #endif /* STP_USE_DWARF_UNWINDER */ |