[Forensics-changes] [yara] 173/415: Harden yr_arena_load against corrupt files and document the arena module

Hilko Bengen bengen at moszumanska.debian.org
Thu Apr 3 05:43:02 UTC 2014


This is an automated email from the git hooks/post-receive script.

bengen pushed a commit to branch debian
in repository yara.

commit 3e5cfcb7956643a3eb29155953a576231e93e625
Author: Victor M. Alvarez <plusvic at gmail.com>
Date:   Thu Jun 13 16:00:56 2013 +0000

    Harden yr_arena_load against corrupt files and document the arena module
---
 libyara/arena.c | 297 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 291 insertions(+), 6 deletions(-)

diff --git a/libyara/arena.c b/libyara/arena.c
index 6234731..a22598f 100644
--- a/libyara/arena.c
+++ b/libyara/arena.c
@@ -14,12 +14,13 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
+
 /*
 
-This module implements a data structure "arena". An arena is a data
-container composed of a set of pages. The arena grows automatically
-when needed, by adding new pages to hold new data if required. Arenas
-can be saved and loaded from files.
+This module implements a structure I've called "arena". An arena is a data
+container composed of a set of pages. The arena grows automatically when
+needed by adding new pages to hold new data. Arenas can be saved and loaded
+from files.
 
 */
 
@@ -50,6 +51,18 @@ typedef struct _ARENA_FILE_HEADER
     ((page)->size - (page)->used)
 
 
+//
+// _yr_arena_new_page
+//
+// Creates a new arena page of a given size
+//
+// Args:
+//    int size  - Size of the page
+//
+// Returns:
+//    A pointer to the newly created ARENA_PAGE structure
+//
+
 ARENA_PAGE* _yr_arena_new_page(
     int size)
 {
@@ -78,6 +91,20 @@ ARENA_PAGE* _yr_arena_new_page(
 }
 
 
+//
+// _yr_arena_page_for_address
+//
+// Returns the page within he arena where an address reside.
+//
+// Args:
+//    ARENA* arena   - Pointer to the arena
+//    void* address  - Address to be located
+//
+// Returns:
+//    A pointer the corresponding ARENA_PAGE structure where the address
+//    resides.
+//
+
 ARENA_PAGE* _yr_arena_page_for_address(
     ARENA* arena,
     void* address)
@@ -98,6 +125,20 @@ ARENA_PAGE* _yr_arena_page_for_address(
 }
 
 
+//
+// _yr_arena_make_relocatable
+//
+// Tells the arena that certain addresses contains a relocatable pointer.
+//
+// Args:
+//    ARENA* arena    - Pointer the arena
+//    void* address   - Base address
+//    va_list offsets - List of offsets relative to base address
+//
+// Returns:
+//    ERROR_SUCCESS if succeed or the corresponding error code otherwise.
+//
+
 int _yr_arena_make_relocatable(
     ARENA* arena,
     void* base,
@@ -144,6 +185,19 @@ int _yr_arena_make_relocatable(
 }
 
 
+//
+// yr_arena_create
+//
+// Creates a new arena.
+//
+// Args:
+//    ARENA** arena  - Address where a pointer to the new arena will be
+//                     written to.
+//
+// Returns:
+//    ERROR_SUCCESS if succeed or the corresponding error code otherwise.
+//
+
 int yr_arena_create(
     ARENA** arena)
 {
@@ -173,6 +227,18 @@ int yr_arena_create(
 }
 
 
+//
+// yr_arena_destroy
+//
+// Destroys an arena releasing its resource.
+//
+// Args:
+//    ARENA* arena  - Pointer to the arena.
+//
+// Returns:
+//    ERROR_SUCCESS if succeed or the corresponding error code otherwise.
+//
+
 void yr_arena_destroy(
     ARENA* arena)
 {
@@ -205,6 +271,18 @@ void yr_arena_destroy(
 }
 
 
+//
+// yr_arena_base_address
+//
+// Returns the base address for the arena.
+//
+// Args:
+//    ARENA* arena  - Pointer to the arena.
+//
+// Returns:
+//    A pointer
+//
+
 void* yr_arena_base_address(
   ARENA* arena)
 {
@@ -212,6 +290,19 @@ void* yr_arena_base_address(
 }
 
 
+//
+// yr_arena_current_address
+//
+// Returns the current address for the arena, which is the address
+// where the next write operation or memory allocation will be done.
+//
+// Args:
+//    ARENA* arena  - Pointer to the arena.
+//
+// Returns:
+//    A pointer
+//
+
 void* yr_arena_current_address(
   ARENA* arena)
 {
@@ -219,6 +310,23 @@ void* yr_arena_current_address(
 }
 
 
+//
+// yr_arena_next_address
+//
+// Given an address and an increment value, returns the address where
+// address + increment resides. The arena is a collection of non-contigous
+// regions of memory (pages), if address is pointing at the end of a page,
+// address + increment could cross the page boundary and point at somewhere
+// within the next page, this function handles these situations.
+//
+// Args:
+//    ARENA* arena  - Pointer to the arena.
+//
+// Returns:
+//    A pointer
+//
+
+
 void* yr_arena_next_address(
   ARENA* arena,
   void* address,
@@ -237,6 +345,19 @@ void* yr_arena_next_address(
 }
 
 
+//
+// yr_arena_coalesce
+//
+// Coalesce the arena into a single page. This is a required step before
+// saving the arena to a file.
+//
+// Args:
+//    ARENA* arena  - Pointer to the arena.
+//
+// Returns:
+//    ERROR_SUCCESS if succeed or the corresponding error code otherwise.
+//
+
 int yr_arena_coalesce(
     ARENA* arena)
 {
@@ -329,6 +450,20 @@ int yr_arena_coalesce(
 }
 
 
+//
+// yr_arena_allocate_memory
+//
+// Allocates memory within the arena.
+//
+// Args:
+//    ARENA* arena - Pointer to the arena.
+//    int32_t size - Size of the region to be allocated.
+//    void** allocated_memory - Address of a pointer to newly allocated
+//                              region.
+// Returns:
+//    ERROR_SUCCESS if succeed or the corresponding error code otherwise.
+//
+
 int yr_arena_allocate_memory(
     ARENA* arena,
     int32_t size,
@@ -385,6 +520,37 @@ int yr_arena_allocate_memory(
 }
 
 
+//
+// yr_arena_allocate_struct
+//
+// Allocates a structure within the arena. This function is similar to
+// yr_arena_allocate_memory but additionaly receives a variable-length
+// list of offsets within the structure where pointers reside. This allows
+// the arena to keep track of pointers that must be adjusted when memory
+// is relocated. This is an example on how to invoke this function:
+//
+//  yr_arena_allocate_struct(
+//        arena,
+//        sizeof(MY_STRUCTURE),
+//        (void**) &my_structure_ptr,
+//        offsetof(MY_STRUCTURE, field_1),
+//        offsetof(MY_STRUCTURE, field_2),
+//        ..
+//        offsetof(MY_STRUCTURE, field_N),
+//        EOL);
+//
+// Args:
+//    ARENA* arena - Pointer to the arena.
+//    int32_t size - Size of the region to be allocated.
+//    void** allocated_memory - Address of a pointer to newly allocated
+//                              region.
+//    ...          - Variable number of offsets relative to beginning of
+//                   the struct. Offsets are if type size_t.
+//
+// Returns:
+//    ERROR_SUCCESS if succeed or the corresponding error code otherwise.
+//
+
 int yr_arena_allocate_struct(
     ARENA* arena,
     int32_t size,
@@ -409,6 +575,21 @@ int yr_arena_allocate_struct(
 }
 
 
+//
+// yr_arena_make_relocatable
+//
+// Tells the arena that certain addresses contains a relocatable pointer.
+//
+// Args:
+//    ARENA* arena    - Pointer to the arena.
+//    void* base      - Address within the arena.
+//    ...             - Variable number of size_t arguments with offsets
+//                      relative to base.
+//
+// Returns:
+//    ERROR_SUCCESS if succeed or the corresponding error code otherwise.
+//
+
 int yr_arena_make_relocatable(
     ARENA* arena,
     void* base,
@@ -427,6 +608,22 @@ int yr_arena_make_relocatable(
 }
 
 
+//
+// yr_arena_write_data
+//
+// Writes data to the arena.
+//
+// Args:
+//    ARENA* arena        - Pointer to the arena.
+//    void* data          - Pointer to data to be written.
+//    int32_t size        - Size of data.
+//    void** written_data - Address where a pointer to the written data will
+//                          be returned.
+//
+// Returns:
+//    ERROR_SUCCESS if succeed or the corresponding error code otherwise.
+//
+
 int yr_arena_write_data(
     ARENA* arena,
     void* data,
@@ -458,6 +655,21 @@ int yr_arena_write_data(
 }
 
 
+//
+// yr_arena_write_string
+//
+// Writes string to the arena.
+//
+// Args:
+//    ARENA* arena           - Pointer to the arena.
+//    const char* string     - Pointer to string to be written.
+//    void** written_string  - Address where a pointer to the written data will
+//                             be returned.
+//
+// Returns:
+//    ERROR_SUCCESS if succeed or the corresponding error code otherwise.
+//
+
 int yr_arena_write_string(
     ARENA* arena,
     const char* string,
@@ -471,6 +683,20 @@ int yr_arena_write_string(
 }
 
 
+//
+// yr_arena_append
+//
+// Appends source_arena to target_arena. This operation destroys source_arena,
+// after returning any pointer to source_arena is no longer valid.
+//
+// Args:
+//    ARENA* target_arena    - Pointer to target the arena.
+//    ARENA* source_arena    - Pointer to source arena.
+//
+// Returns:
+//    ERROR_SUCCESS if succeed or the corresponding error code otherwise.
+//
+
 int yr_arena_append(
     ARENA* target_arena,
     ARENA* source_arena)
@@ -484,6 +710,21 @@ int yr_arena_append(
 }
 
 
+//
+// yr_arena_duplicate
+//
+// Duplicates the arena, making an exact copy. This function requires the
+// arena to be coalesced.
+//
+// Args:
+//    ARENA* arena        - Pointer to the arena.
+//    ARENA** duplicated  - Address where a pointer to the new arena arena will
+//                          be returned.
+//
+// Returns:
+//    ERROR_SUCCESS if succeed or the corresponding error code otherwise.
+//
+
 int yr_arena_duplicate(
     ARENA* arena,
     ARENA** duplicated)
@@ -563,6 +804,20 @@ int yr_arena_duplicate(
 }
 
 
+//
+// yr_arena_save
+//
+// Saves the arena into a file. If the file exists its overwritten. This
+// function requires the arena to be coalesced.
+//
+// Args:
+//    ARENA* arena          - Pointer to the arena.
+//    const char* filename  - File path.
+//
+// Returns:
+//    ERROR_SUCCESS if succeed or the corresponding error code otherwise.
+//
+
 int yr_arena_save(
   ARENA* arena,
   const char* filename)
@@ -641,6 +896,20 @@ int yr_arena_save(
 }
 
 
+//
+// yr_arena_load
+//
+// Loads an arena from a file.
+//
+// Args:
+//    const char* filename  - File path.
+//    ARENA**               - Address where a pointer to the loaded arena
+//                            will be returned.
+//
+// Returns:
+//    ERROR_SUCCESS if succeed or the corresponding error code otherwise.
+//
+
 int yr_arena_load(
     const char* filename,
     ARENA** arena)
@@ -655,13 +924,19 @@ int yr_arena_load(
   int32_t reloc_offset;
   void** reloc_address;
   void* reloc_target;
+  long file_size;
 
   fh = fopen(filename, "r");
 
   if (fh == NULL)
     return ERROR_COULD_NOT_OPEN_FILE;
 
+  fseek(fh, 0, SEEK_END);
+  file_size = ftell(fh);
+  fseek(fh, 0, SEEK_SET);
+
   if (fread(&header, sizeof(header), 1, fh) != 1 ||
+      header.size >= file_size ||
       header.magic[0] != 'Y' ||
       header.magic[1] != 'A' ||
       header.magic[2] != 'R' ||
@@ -705,7 +980,12 @@ int yr_arena_load(
 
   page->used = header.size;
 
-  fread(&reloc_offset, sizeof(reloc_offset), 1, fh);
+  if (fread(&reloc_offset, sizeof(reloc_offset), 1, fh) != 1)
+  {
+    fclose(fh);
+    yr_arena_destroy(new_arena);
+    return ERROR_INVALID_OR_CORRUPT_FILE;
+  }
 
   while (reloc_offset != -1)
   {
@@ -719,7 +999,12 @@ int yr_arena_load(
     else
       *reloc_address = 0;
 
-    fread(&reloc_offset, sizeof(reloc_offset), 1, fh);
+    if (fread(&reloc_offset, sizeof(reloc_offset), 1, fh) != 1)
+    {
+      fclose(fh);
+      yr_arena_destroy(new_arena);
+      return ERROR_INVALID_OR_CORRUPT_FILE;
+    }
   }
 
   fclose(fh);

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/forensics/yara.git



More information about the forensics-changes mailing list