1 #include <string.h>
2 #include <assert.h>
3 #include <signal.h>
4 #include <stdio.h>
5 #include <setjmp.h>
6 
7 #include "vtv_malloc.h"
8 #include "../../../include/vtv-change-permission.h"
9 
10 volatile static int signal_count = 0;
11 
12 sigjmp_buf before_segv;
13 
14 unsigned int vtv_debug = 0;
15 
16 static void
handler(int sig,siginfo_t * si,void * unused)17 handler(int sig, siginfo_t *si, void *unused)
18 {
19   signal_count++;
20   /* You are not supposed to longjmp out of a signal handler but it seems
21      to work for this test case and it simplifies it */
22   siglongjmp(before_segv, 1);
23 }
24 
25 /* Try to modify the memory pointed by "s" but dont actually change the values.
26    Assumes and verifies the memory to be modified is mprotected */
mempoke(void * s,size_t n)27 void mempoke(void * s, size_t n)
28 {
29   volatile char * p = (char *)s;
30   int ret;
31 
32   signal_count = 0;
33   ret = sigsetjmp(before_segv, 1);
34   if (ret == 0)
35     p[0] = p[0];
36 
37   assert(ret == 1 && signal_count == 1);
38 
39   ret = sigsetjmp(before_segv, 1);
40   if (ret == 0)
41     p[n - 1] = p[n - 1];
42 
43   assert(ret == 1 && signal_count == 2);
44 }
45 
main()46 int main()
47 {
48   char * ptr;
49   int size;
50 
51   /* Set up handler for SIGSEGV. */
52   struct sigaction sa;
53   sa.sa_flags = SA_SIGINFO;
54   sigemptyset(&sa.sa_mask);
55   sa.sa_sigaction = handler;
56   if (sigaction(SIGSEGV, &sa, NULL) == -1)
57     assert(0);
58 
59   /* Make the 'bookkeeping' vars read-write.  */
60   __VLTChangePermission (__VLTP_READ_WRITE);
61   __vtv_malloc_init();
62 
63   size = 10;
64 
65   /* Verify not writable after unprotect */
66   __vtv_malloc_unprotect();
67   ptr = (char *)__vtv_malloc(size);
68   memset(ptr, 'a', size);
69   __vtv_malloc_protect();
70   mempoke(ptr, size);
71   __vtv_free(ptr);
72 
73   /* verify not-writable after protect, unprotect */
74   __vtv_malloc_unprotect();
75   ptr = (char *)__vtv_malloc(size);
76   memset(ptr, 'a', size);
77   __vtv_malloc_protect();
78   __vtv_malloc_unprotect();
79   memset(ptr, 'a', size);
80   assert(ptr[size - 1] == 'a');
81   __vtv_malloc_protect();
82   assert(ptr[size - 1] == 'a');
83   mempoke(ptr,size);
84   __vtv_free(ptr);
85 
86   /* Allocate a bunch of small objects.
87      Make sure the alignment is correct.
88      Verify data has not been corrupted.
89      Make sure the data cannot modified */
90   {
91     int s;
92     for (s = 3; s < 28; s += 3)
93     {
94       size = s;
95       {
96         int i;
97         #define ITERS 1000
98         char * ptrs[ITERS];
99 
100         __vtv_malloc_unprotect();
101         for (i = 0; i < ITERS; i++)
102         {
103           ptr = (char *)__vtv_malloc(size);
104           assert(((long)ptr & VTV_ALIGNMENT_MASK) == 0);
105           memset(ptr, (i & 127), size);
106           assert(ptr[size - 1] == (i & 127));
107           ptrs[i] = ptr;
108         }
109         __vtv_malloc_protect();
110 
111         for (i = 0; i < ITERS; i++)
112           mempoke(ptrs[i], size);
113 
114         __vtv_malloc_unprotect();
115         for (i = 0; i < ITERS; i++)
116           __vtv_free(ptrs[i]);
117         __vtv_malloc_protect();
118       }
119     }
120   }
121 
122   /* Allocate a bunch of medium size objects.
123      Make sure the alignment is correct.
124      Verify data has not been corrupted.
125      Try to modify the data to verify everything gets unprotected */
126   {
127     int s;
128     for (s = 501; s < 2500; s += 91)
129     {
130       size = s;
131       {
132         int i;
133         #define ITERS2 100
134         char * ptrs[ITERS2];
135 
136         __vtv_malloc_unprotect();
137         for (i = 0; i < ITERS2; i++)
138         {
139 
140           ptr = (char *)__vtv_malloc(size);
141           assert(((long)ptr & VTV_ALIGNMENT_MASK) == 0);
142           memset(ptr, i & 127, size);
143           assert(ptr[size - 1] == i & 127);
144           ptrs[i] = ptr;
145         }
146         __vtv_malloc_protect();
147 
148         for (i = 0; i < ITERS2; i++)
149           mempoke(ptrs[i], size);
150 
151         __vtv_malloc_unprotect();
152         for (i = 0; i < ITERS2; i++)
153           __vtv_free(ptrs[i]);
154         __vtv_malloc_protect();
155       }
156     }
157   }
158 
159   /* Allocate a bunch of medium size objects. Make sure the alignment is correct */
160   {
161     int s;
162     for (s = 3001; s < 15000; s += 307)
163     {
164       size = s;
165       {
166         int i;
167         #define ITERS3 50
168         char * ptrs[ITERS3];
169 
170         __vtv_malloc_unprotect();
171         for (i = 0; i < ITERS3; i++)
172         {
173           ptr = (char *)__vtv_malloc(size);
174           assert(((long)ptr & VTV_ALIGNMENT_MASK) == 0);
175           memset(ptr, i & 127, size);
176           assert(ptr[size - 1] == i & 127);
177           ptrs[i] = ptr;
178         }
179         __vtv_malloc_protect();
180 
181         for (i = 0; i < ITERS3; i++)
182           mempoke(ptrs[i], size);
183 
184         __vtv_malloc_unprotect();
185         for (i = 0; i < ITERS3; i++)
186           __vtv_free(ptrs[i]);
187         __vtv_malloc_protect();
188       }
189     }
190   }
191 
192   return 0;
193 }
194