fix memory leak
[trinity.git] / tables-biarch.c
blob4b46200add45ef22d4977b7d4ddc42eb7e021b47
1 /*
2 * Functions for handling the system call tables.
3 * These functions are only used on architectures that have both 32 and 64 bit syscalls.
4 */
6 #include <string.h>
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <stdlib.h>
11 #include "trinity.h" // ARRAY_SIZE, alloc_shared
12 #include "arch.h"
13 #include "syscall.h"
14 #include "params.h"
15 #include "log.h"
16 #include "shm.h"
17 #include "tables.h"
19 #define NOTFOUND (unsigned int)-1
21 const struct syscalltable *syscalls_32bit;
22 const struct syscalltable *syscalls_64bit;
24 unsigned int max_nr_32bit_syscalls;
25 unsigned int max_nr_64bit_syscalls;
27 bool use_32bit = FALSE;
28 bool use_64bit = FALSE;
30 void activate_syscall32(unsigned int calln)
32 activate_syscall_in_table(calln, &shm->nr_active_32bit_syscalls, syscalls_32bit, shm->active_syscalls32);
35 void activate_syscall64(unsigned int calln)
37 activate_syscall_in_table(calln, &shm->nr_active_64bit_syscalls, syscalls_64bit, shm->active_syscalls64);
40 void deactivate_syscall32(unsigned int calln)
42 deactivate_syscall_in_table(calln, &shm->nr_active_32bit_syscalls, syscalls_32bit, shm->active_syscalls32);
45 void deactivate_syscall64(unsigned int calln)
47 deactivate_syscall_in_table(calln, &shm->nr_active_64bit_syscalls, syscalls_64bit, shm->active_syscalls64);
51 int validate_syscall_table_64(void)
53 if (shm->nr_active_64bit_syscalls == 0)
54 use_64bit = FALSE;
55 else
56 use_64bit = TRUE;
58 return use_64bit;
61 int validate_syscall_table_32(void)
63 if (shm->nr_active_32bit_syscalls == 0)
64 use_32bit = FALSE;
65 else
66 use_32bit = TRUE;
68 return use_32bit;
71 void toggle_syscall_biarch_n(int calln, const struct syscalltable *table, bool onlyflag, bool doflag, bool state, void (*activate)(unsigned int), int arch_bits, const char *arg_name)
73 if (calln != -1) {
74 validate_specific_syscall(table, calln);
76 if ((state == TRUE) && onlyflag && doflag) {
77 table[calln].entry->flags |= ACTIVE;
78 (*activate)(calln);
79 } else {
80 table[calln].entry->flags |= TO_BE_DEACTIVATED;
84 if ((arch_bits != 0) && (calln != -1))
85 output(0, "Marking %d-bit syscall %s (%d) as to be %sabled.\n",
86 arch_bits, arg_name, calln,
87 state ? "en" : "dis");
90 void toggle_syscall_biarch(const char *arg, bool state)
92 int specific_syscall32 = 0;
93 int specific_syscall64 = 0;
94 char *arg_name = NULL;
95 bool only_32bit = TRUE;
96 bool only_64bit = TRUE;
98 check_user_specified_arch(arg, &arg_name, &only_64bit, &only_32bit);
100 /* If we found a 64bit syscall, validate it. */
101 specific_syscall64 = search_syscall_table(syscalls_64bit, max_nr_64bit_syscalls, arg_name);
102 toggle_syscall_biarch_n(specific_syscall64, syscalls_64bit, only_64bit, do_64_arch, state, &activate_syscall64, 0, arg_name);
104 /* Search for and validate 32bit */
105 specific_syscall32 = search_syscall_table(syscalls_32bit, max_nr_32bit_syscalls, arg_name);
106 toggle_syscall_biarch_n(specific_syscall32, syscalls_32bit, only_32bit, do_32_arch, state, &activate_syscall32, 0, arg_name);
109 if ((!only_32bit) && (!only_64bit)) {
110 outputerr("No idea what architecture for syscall (%s) is.\n", arg);
111 exit(EXIT_FAILURE);
114 if ((specific_syscall64 == -1) && (specific_syscall32 == -1)) {
115 outputerr("No idea what syscall (%s) is.\n", arg);
116 exit(EXIT_FAILURE);
119 if ((specific_syscall64 != -1) && (specific_syscall32 != -1)) {
120 output(0, "Marking syscall %s (64bit:%d 32bit:%d) as to be %sabled.\n",
121 arg_name, specific_syscall64, specific_syscall32,
122 state ? "en" : "dis");
123 clear_check_user_specified_arch(arg, &arg_name);
124 return;
127 if (specific_syscall64 != -1) {
128 output(0, "Marking 64-bit syscall %s (%d) as to be %sabled.\n",
129 arg, specific_syscall64,
130 state ? "en" : "dis");
131 clear_check_user_specified_arch(arg, &arg_name);
132 return;
135 if (specific_syscall32 != -1) {
136 output(0, "Marking 32-bit syscall %s (%d) as to be %sabled.\n",
137 arg, specific_syscall32,
138 state ? "en" : "dis");
139 clear_check_user_specified_arch(arg, &arg_name);
140 return;
144 void enable_random_syscalls_biarch(void)
146 unsigned int call32 = NOTFOUND, call64 = NOTFOUND;
148 retry:
150 //Search for 64 bit version
151 if (do_64_arch) {
152 call64 = rand() % max_nr_64bit_syscalls;
153 if (validate_specific_syscall_silent(syscalls_64bit, call64) == FALSE)
154 goto retry;
156 if (no_files == TRUE)
157 if (is_syscall_net_related(syscalls_64bit, call64) == FALSE)
158 goto retry;
160 if (syscalls_64bit[call64].entry->flags & TO_BE_DEACTIVATED)
161 goto try32bit;
163 if (syscalls_64bit[call64].entry->active_number != 0)
164 goto try32bit;
166 // If we got so far, then activate it.
167 toggle_syscall_biarch_n(call64, syscalls_64bit, TRUE, do_64_arch, TRUE,
168 &activate_syscall64, 64, syscalls_64bit[call64].entry->name);
171 try32bit:
172 //Search for 32 bit version
173 if (do_32_arch) {
175 // FIXME: WTF is going on here?
176 if (do_64_arch) {
177 call32 = search_syscall_table(syscalls_32bit, max_nr_32bit_syscalls, syscalls_64bit[call64].entry->name);
179 if (syscalls_64bit[call64].entry->flags & TO_BE_DEACTIVATED)
180 call64 = NOTFOUND; //mark as not found in order not to increment i.
181 } else {
182 call32 = rand() % max_nr_32bit_syscalls;
185 if (validate_specific_syscall_silent(syscalls_32bit, call32) == FALSE) {
186 if (call64 == NOTFOUND)
187 goto retry;
188 else
189 return;
192 if (no_files == TRUE) {
193 if (is_syscall_net_related(syscalls_32bit, call32) == FALSE) {
194 if (call64 == NOTFOUND)
195 goto retry;
196 else
197 return;
201 if ((syscalls_32bit[call32].entry->flags & TO_BE_DEACTIVATED) || (syscalls_32bit[call32].entry->active_number != 0)) {
202 if (call64 == NOTFOUND)
203 goto retry;
204 else
205 return;
208 //If we got so far, then active it.
209 toggle_syscall_biarch_n(call32, syscalls_32bit, TRUE, do_32_arch, TRUE,
210 &activate_syscall32, 32, syscalls_32bit[call32].entry->name);
214 void disable_non_net_syscalls_biarch(void)
216 unsigned int i;
218 for_each_64bit_syscall(i) {
219 if (validate_specific_syscall_silent(syscalls_64bit, i) == FALSE)
220 continue;
222 if (syscalls_64bit[i].entry->flags & ACTIVE) {
223 if (is_syscall_net_related(syscalls_64bit, i) == FALSE) {
224 toggle_syscall_biarch_n(i, syscalls_64bit, FALSE, do_64_arch, FALSE,
225 &activate_syscall64, 64, syscalls_64bit[i].entry->name);
230 for_each_32bit_syscall(i) {
231 if (validate_specific_syscall_silent(syscalls_32bit, i) == FALSE)
232 continue;
234 if (syscalls_32bit[i].entry->flags & ACTIVE) {
235 if (is_syscall_net_related(syscalls_32bit, i) == FALSE) {
236 toggle_syscall_biarch_n(i, syscalls_32bit, FALSE, do_32_arch, FALSE,
237 &activate_syscall32, 32, syscalls_32bit[i].entry->name);
243 int setup_syscall_group_biarch(unsigned int group)
245 unsigned int i;
247 for_each_32bit_syscall(i) {
248 if (syscalls_32bit[i].entry->group == group)
249 activate_syscall32(i);
252 if (shm->nr_active_32bit_syscalls == 0)
253 outputstd("No 32-bit syscalls in group\n");
254 else
255 outputstd("Found %d 32-bit syscalls in group\n", shm->nr_active_32bit_syscalls);
257 /* now the 64 bit table*/
258 for_each_64bit_syscall(i) {
259 if (syscalls_64bit[i].entry->group == group)
260 activate_syscall64(i);
263 if (shm->nr_active_64bit_syscalls == 0) {
264 outputstd("No 64-bit syscalls in group\n");
265 return FALSE;
266 } else {
267 outputstd("Found %d 64-bit syscalls in group\n", shm->nr_active_64bit_syscalls);
270 return TRUE;
273 void mark_all_syscalls_active_biarch(void)
275 unsigned int i;
277 if (do_32_arch) {
278 for_each_32bit_syscall(i) {
279 syscalls_32bit[i].entry->flags |= ACTIVE;
280 activate_syscall32(i);
284 if (do_64_arch) {
285 for_each_64bit_syscall(i) {
286 syscalls_64bit[i].entry->flags |= ACTIVE;
287 activate_syscall64(i);
292 void init_syscalls_biarch(void)
294 unsigned int i;
296 for_each_64bit_syscall(i) {
297 if (syscalls_64bit[i].entry->flags & ACTIVE)
298 if (syscalls_64bit[i].entry->init)
299 syscalls_64bit[i].entry->init();
302 for_each_32bit_syscall(i) {
303 if (syscalls_32bit[i].entry->flags & ACTIVE)
304 if (syscalls_32bit[i].entry->init)
305 syscalls_32bit[i].entry->init();
309 void deactivate_disabled_syscalls_biarch(void)
311 unsigned int i;
313 for_each_64bit_syscall(i) {
314 if (syscalls_64bit[i].entry->flags & TO_BE_DEACTIVATED) {
315 syscalls_64bit[i].entry->flags &= ~(ACTIVE|TO_BE_DEACTIVATED);
316 deactivate_syscall64(i);
317 output(0, "Marked 64-bit syscall %s (%d) as deactivated.\n",
318 syscalls_64bit[i].entry->name, syscalls_64bit[i].entry->number);
322 for_each_32bit_syscall(i) {
323 if (syscalls_32bit[i].entry->flags & TO_BE_DEACTIVATED) {
324 syscalls_32bit[i].entry->flags &= ~(ACTIVE|TO_BE_DEACTIVATED);
325 deactivate_syscall32(i);
326 output(0, "Marked 32-bit syscall %s (%d) as deactivated.\n",
327 syscalls_32bit[i].entry->name, syscalls_32bit[i].entry->number);
332 void dump_syscall_tables_biarch(void)
334 unsigned int i;
336 outputstd("syscalls: %d [32-bit]\n", max_nr_32bit_syscalls);
337 outputstd("syscalls: %d [64-bit]\n", max_nr_64bit_syscalls);
339 for_each_32bit_syscall(i) {
340 outputstd("entrypoint %d %s : [32-bit] ",
341 syscalls_32bit[i].entry->number,
342 syscalls_32bit[i].entry->name);
343 show_state(syscalls_32bit[i].entry->flags & ACTIVE);
345 if (syscalls_32bit[i].entry->flags & AVOID_SYSCALL)
346 outputstd(" AVOID");
347 outputstd("\n");
350 for_each_64bit_syscall(i) {
351 outputstd("entrypoint %d %s : [64-bit] ",
352 syscalls_64bit[i].entry->number,
353 syscalls_64bit[i].entry->name);
354 show_state(syscalls_64bit[i].entry->flags & ACTIVE);
355 if (syscalls_64bit[i].entry->flags & AVOID_SYSCALL)
356 outputstd(" AVOID");
358 outputstd("\n");
362 void display_enabled_syscalls_biarch(void)
364 unsigned int i;
366 for_each_64bit_syscall(i) {
367 if (syscalls_64bit[i].entry->flags & ACTIVE)
368 output(0, "64-bit syscall %d:%s enabled.\n", i, syscalls_64bit[i].entry->name);
371 for_each_32bit_syscall(i) {
372 if (syscalls_32bit[i].entry->flags & ACTIVE)
373 output(0, "32-bit syscall %d:%s enabled.\n", i, syscalls_32bit[i].entry->name);