]> sourceware.org Git - systemtap.git/commitdiff
Be paranoid about table size resolving cie_for_fde and fde_pointer_type.
authorMark Wielaard <mjw@redhat.com>
Tue, 20 Oct 2009 11:55:15 +0000 (13:55 +0200)
committerMark Wielaard <mjw@redhat.com>
Tue, 20 Oct 2009 11:55:15 +0000 (13:55 +0200)
* runtime/unwind.c (cie_for_fde): Take table and table_len into account.
  (fde_pointer_type): Likewise.
* runtime/unwind/unwind.h: Adjust function prototypes.

runtime/unwind.c
runtime/unwind/unwind.h

index 00108a39168cf34f2e39fcdf4bccfd93dbefe4a1..0b4e6a9effeb6dc00cc03d391082d81fee2f0a98 100644 (file)
@@ -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 != &not_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 == &not_fde || (ptrType = fde_pointer_type(cie)) < 0)
+                       if (cie == NULL || cie == &not_fde || (ptrType = fde_pointer_type(cie, table, table_len)) < 0)
                                continue;
 
                        ptr = (const u8 *)(fde + 2);
index 285a3a347ab52c8c236039e1e9d39c56a20dee61..023ea603d69f5262888d34745807381817458ecc 100644 (file)
@@ -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 */
This page took 0.034708 seconds and 5 git commands to generate.