split deactivate_disabled_syscalls into uni/biarch
[trinity.git] / trinity.c
blob63f205ceda50c478d8d10417ae7aa08863387a5d
1 #include <errno.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <stdarg.h>
5 #include <stdio.h>
6 #include <time.h>
7 #include <ctype.h>
8 #include <unistd.h>
9 #include <setjmp.h>
10 #include <malloc.h>
11 #include <asm/unistd.h>
12 #include <sys/time.h>
13 #include <sys/stat.h>
14 #include <sys/types.h>
15 #include <sys/wait.h>
16 #include <sys/syscall.h>
17 #include <sys/ipc.h>
18 #include <sys/mman.h>
19 #include <sys/socket.h>
21 #include "arch.h"
22 #include "trinity.h"
23 #include "files.h"
24 #include "log.h"
25 #include "maps.h"
26 #include "pids.h"
27 #include "net.h"
28 #include "params.h"
29 #include "random.h"
30 #include "signals.h"
31 #include "shm.h"
32 #include "syscall.h"
33 #include "ioctls.h"
34 #include "config.h" // for VERSION
36 char *progname = NULL;
38 unsigned int page_size;
39 unsigned int num_online_cpus;
41 struct shm_s *shm;
43 #define SHM_PROT_PAGES 30
45 static int create_shm(void)
47 void *p;
48 unsigned int shm_pages;
50 shm_pages = ((sizeof(struct shm_s) + page_size - 1) & ~(page_size - 1)) / page_size;
52 /* Waste some address space to set up some "protection" near the SHM location. */
53 p = alloc_shared((SHM_PROT_PAGES + shm_pages + SHM_PROT_PAGES) * page_size);
54 if (p == NULL) {
55 perror("mmap");
56 return -1;
59 mprotect(p, SHM_PROT_PAGES * page_size, PROT_NONE);
60 mprotect(p + (SHM_PROT_PAGES + shm_pages) * page_size,
61 SHM_PROT_PAGES * page_size, PROT_NONE);
63 shm = p + SHM_PROT_PAGES * page_size;
65 memset(shm, 0, sizeof(struct shm_s));
67 shm->total_syscalls_done = 1;
68 shm->regenerate = 0;
70 memset(shm->pids, EMPTY_PIDSLOT, sizeof(shm->pids));
72 shm->nr_active_syscalls = 0;
73 shm->nr_active_32bit_syscalls = 0;
74 shm->nr_active_64bit_syscalls = 0;
75 memset(shm->active_syscalls, 0, sizeof(shm->active_syscalls));
76 memset(shm->active_syscalls32, 0, sizeof(shm->active_syscalls32));
77 memset(shm->active_syscalls64, 0, sizeof(shm->active_syscalls64));
79 /* Overwritten later in setup_shm_postargs if user passed -s */
80 shm->seed = new_seed();
82 /* Set seed in parent thread */
83 set_seed(0);
85 return 0;
88 static void setup_shm_postargs(void)
90 if (user_set_seed == TRUE) {
91 shm->seed = init_seed(seed);
92 /* Set seed in parent thread */
93 set_seed(0);
96 if (user_specified_children != 0)
97 shm->max_children = user_specified_children;
98 else
99 shm->max_children = sysconf(_SC_NPROCESSORS_ONLN);
101 if (shm->max_children > MAX_NR_CHILDREN) {
102 outputerr("Increase MAX_NR_CHILDREN!\n");
103 exit(EXIT_FAILURE);
107 /* This is run *after* we've parsed params */
108 static int munge_tables(void)
110 unsigned int ret;
112 /* By default, all syscall entries will be disabled.
113 * If we didn't pass -c, -x or -r, mark all syscalls active.
115 if ((do_specific_syscall == FALSE) && (do_exclude_syscall == FALSE) && (random_selection == FALSE) && (desired_group == GROUP_NONE))
116 mark_all_syscalls_active();
118 if (desired_group != GROUP_NONE) {
119 ret = setup_syscall_group(desired_group);
120 if (ret == FALSE)
121 return FALSE;
124 if (random_selection == TRUE)
125 enable_random_syscalls();
127 /* If we saw a '-x', set all syscalls to enabled, then selectively disable.
128 * Unless we've started enabling them already (with -r)
130 if (do_exclude_syscall == TRUE) {
131 if (random_selection == FALSE)
132 mark_all_syscalls_active();
133 deactivate_disabled_syscalls();
136 /* if we passed -n, make sure there's no VM/VFS syscalls enabled. */
137 if (no_files == TRUE)
138 disable_non_net_syscalls();
140 sanity_check_tables();
142 count_syscalls_enabled();
144 if (verbose == TRUE)
145 display_enabled_syscalls();
147 if (validate_syscall_tables() == FALSE) {
148 outputstd("No syscalls were enabled!\n");
149 outputstd("Use 32bit:%d 64bit:%d\n", use_32bit, use_64bit);
150 return FALSE;
153 return TRUE;
157 * just in case we're not using the test.sh harness, we
158 * change to the tmp dir if it exists.
160 static void change_tmp_dir(void)
162 struct stat sb;
163 const char tmpdir[]="tmp/";
164 int ret;
166 /* Check if it exists, bail early if it doesn't */
167 ret = (lstat(tmpdir, &sb));
168 if (ret == -1)
169 return;
171 /* Just in case a previous run screwed the perms. */
172 ret = chmod(tmpdir, 0755);
173 if (ret == -1)
174 output(0, "Couldn't chmod %s to 0755.\n", tmpdir);
176 ret = chdir(tmpdir);
177 if (ret == -1)
178 output(0, "Couldn't change to %s\n", tmpdir);
182 int main(int argc, char* argv[])
184 int ret = EXIT_SUCCESS;
185 int childstatus;
186 unsigned int i;
188 outputstd("Trinity v" __stringify(VERSION) " Dave Jones <davej@redhat.com>\n");
190 progname = argv[0];
192 initpid = getpid();
194 page_size = getpagesize();
195 num_online_cpus = sysconf(_SC_NPROCESSORS_ONLN);
197 select_syscall_tables();
199 if (create_shm())
200 exit(EXIT_FAILURE);
202 parse_args(argc, argv);
203 outputstd("Done parsing arguments.\n");
205 if (kernel_taint_mask != (int)0xFFFFFFFF) {
206 outputstd("Custom kernel taint mask has been specified: 0x%08x (%d).\n", kernel_taint_mask, kernel_taint_mask);
209 setup_shm_postargs();
211 if (logging == TRUE)
212 open_logfiles();
214 if (munge_tables() == FALSE) {
215 ret = EXIT_FAILURE;
216 goto out;
219 if (show_syscall_list == TRUE) {
220 dump_syscall_tables();
221 goto out;
224 init_syscalls();
226 if (show_ioctl_list == TRUE) {
227 dump_ioctls();
228 goto out;
231 if (getuid() == 0) {
232 if (dangerous == TRUE) {
233 outputstd("DANGER: RUNNING AS ROOT.\n");
234 outputstd("Unless you are running in a virtual machine, this could cause serious problems such as overwriting CMOS\n");
235 outputstd("or similar which could potentially make this machine unbootable without a firmware reset.\n\n");
236 outputstd("ctrl-c now unless you really know what you are doing.\n");
237 for (i = 10; i > 0; i--) {
238 outputstd("Continuing in %d seconds.\r", i);
239 (void)fflush(stdout);
240 sleep(1);
242 } else {
243 outputstd("Don't run as root (or pass --dangerous if you know what you are doing).\n");
244 exit(EXIT_FAILURE);
248 if (do_specific_proto == TRUE)
249 find_specific_proto(specific_proto_optarg);
251 init_buffers();
253 parse_devices();
255 pids_init();
257 setup_main_signals();
259 kernel_taint_initial = check_tainted();
260 if (kernel_taint_initial != 0) {
261 output(0, "Kernel was tainted on startup. Will ignore flags that are already set.\n");
264 change_tmp_dir();
266 /* check if we ctrl'c or something went wrong during init. */
267 if (shm->exit_reason != STILL_RUNNING)
268 goto cleanup_fds;
270 init_watchdog();
272 do_main_loop();
274 /* Shutting down. */
275 waitpid(watchdog_pid, &childstatus, 0);
277 output(0, "\nRan %ld syscalls. Successes: %ld Failures: %ld\n",
278 shm->total_syscalls_done - 1, shm->successes, shm->failures);
280 ret = EXIT_SUCCESS;
282 cleanup_fds:
284 for (i = 0; i < nr_sockets; i++) {
285 int r = 0;
286 struct linger ling = { .l_onoff = FALSE, };
288 ling.l_onoff = FALSE; /* linger active */
289 r = setsockopt(shm->socket_fds[i], SOL_SOCKET, SO_LINGER, &ling, sizeof(struct linger));
290 if (r)
291 perror("setsockopt");
292 r = shutdown(shm->socket_fds[i], SHUT_RDWR);
293 if (r)
294 perror("shutdown");
295 close(shm->socket_fds[i]);
298 destroy_maps();
300 if (logging == TRUE)
301 close_logfiles();
303 out:
305 exit(ret);