call fatal if mem_head size is corrupted.
authorAnthony Romano <anthony.romano@coreos.com>
Mon, 17 Jul 2017 03:50:11 +0000 (20:50 -0700)
committerNIIBE Yutaka <gniibe@fsij.org>
Tue, 18 Jul 2017 04:31:06 +0000 (13:31 +0900)
Signed-off-by: Anthony Romano <anthony.romano@coreos.com>
ChangeLog
src/gnuk.h
src/main.c

index 448556d..ca5a387 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2017-07-18  Anthony Romano <anthony.romano@coreos.com>
+
+       * src/main.c (MEMORY_SIZE, MEM_HEAD_IS_CORRUPT, MEM_HEAD_CHECK):
+       New.
+       (gnuk_malloc, gnuk_free): Add calls to MEM_HEAD_CHECK.
+
+       * src/gnuk.h (FATAL_HEAP): New.
+
 2017-07-18  Anthony Romano <anthony.romano@coreos.com>
 
        * src/openpgp-do.c (gpg_reset_algo_attr): New.
index 55ae8e1..15aba51 100644 (file)
@@ -301,6 +301,7 @@ void gpg_increment_digital_signature_counter (void);
 void fatal (uint8_t code) __attribute__ ((noreturn));
 #define FATAL_FLASH  1
 #define FATAL_RANDOM 2
+#define FATAL_HEAP   3
 
 extern uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
 extern uint8_t admin_authorized;
index 5e48bad..f7a576f 100644 (file)
@@ -354,6 +354,7 @@ extern uint8_t __heap_end__[];
 #define MEMORY_END (__heap_end__)
 #define MEMORY_ALIGNMENT 16
 #define MEMORY_ALIGN(n) (((n) + MEMORY_ALIGNMENT - 1) & ~(MEMORY_ALIGNMENT - 1))
+#define MEMORY_SIZE ((uintptr_t)__heap_end__ -  (uintptr_t)__heap_base__)
 
 static uint8_t *heap_p;
 static chopstx_mutex_t malloc_mtx;
@@ -365,6 +366,10 @@ struct mem_head {
   struct mem_head *neighbor;   /* backlink to neighbor */
 };
 
+#define MEM_HEAD_IS_CORRUPT(x) \
+    ((x)->size != MEMORY_ALIGN((x)->size) || (x)->size > MEMORY_SIZE)
+#define MEM_HEAD_CHECK(x) if (MEM_HEAD_IS_CORRUPT(x)) fatal (FATAL_HEAP)
+
 static struct mem_head *free_list;
 
 static void
@@ -421,7 +426,7 @@ gnuk_malloc (size_t size)
            m->size = size;
          break;
        }
-
+      MEM_HEAD_CHECK (m);
       if (m->size == size)
        {
          remove_from_free_list (m);
@@ -466,9 +471,11 @@ gnuk_free (void *p)
   DEBUG_SHORT (m->size);
   DEBUG_WORD ((uint32_t)p);
 
+  MEM_HEAD_CHECK (m);
   m->neighbor = NULL;
   while (m0)
     {
+      MEM_HEAD_CHECK (m0);
       if ((void *)m + m->size == (void *)m0)
        m0->neighbor = m;
       else if ((void *)m0 + m0->size == (void *)m)
@@ -484,6 +491,7 @@ gnuk_free (void *p)
       heap_p -= m->size;
       while (mn)
        {
+         MEM_HEAD_CHECK (mn);
          heap_p -= mn->size;
          remove_from_free_list (mn);
          mn = mn->neighbor;