move shm code out of trinity.c into own file
[trinity.git] / trinity.c
blob62f87abed7e821ee506a1605f01c0774f0c44ae2
1 #include <stdlib.h>
2 #include <malloc.h>
3 #include <string.h>
4 #include <sys/types.h>
5 #include <sys/wait.h>
7 #include "arch.h"
8 #include "trinity.h"
9 #include "files.h"
10 #include "log.h"
11 #include "maps.h"
12 #include "pids.h"
13 #include "params.h"
14 #include "random.h"
15 #include "signals.h"
16 #include "shm.h"
17 #include "tables.h"
18 #include "ioctls.h"
19 #include "protocols.h"
20 #include "config.h" // for VERSION
22 char *progname = NULL;
24 unsigned int page_size;
25 unsigned int num_online_cpus;
27 char *page_zeros;
28 char *page_0xff;
29 char *page_rand;
30 char *page_allocs;
32 static void init_buffers(void)
34 unsigned int i;
36 output(2, "shm is at %p\n", shm);
38 page_zeros = memalign(page_size, page_size * 2);
39 if (!page_zeros)
40 exit(EXIT_FAILURE);
41 memset(page_zeros, 0, page_size);
42 output(2, "page_zeros @ %p\n", page_zeros);
44 page_0xff = memalign(page_size, page_size * 2);
45 if (!page_0xff)
46 exit(EXIT_FAILURE);
47 memset(page_0xff, 0xff, page_size);
48 output(2, "page_0xff @ %p\n", page_0xff);
50 page_rand = memalign(page_size, page_size * 2);
51 if (!page_rand)
52 exit(EXIT_FAILURE);
53 memset(page_rand, 0x55, page_size); /* overwritten below */
54 output(2, "page_rand @ %p\n", page_rand);
56 page_allocs = memalign(page_size, page_size * 2);
57 if (!page_allocs)
58 exit(EXIT_FAILURE);
59 memset(page_allocs, 0xff, page_size);
60 output(2, "page_allocs @ %p\n", page_allocs);
62 for (i = 0; i < (page_size / sizeof(unsigned long *)); i++)
63 page_allocs[i] = (unsigned long) malloc(page_size);
65 setup_global_mappings();
67 // generate_random_page may end up using global_mappings, so has to be last.
68 generate_random_page(page_rand);
71 /* This is run *after* we've parsed params */
72 static int munge_tables(void)
74 unsigned int ret;
76 /* By default, all syscall entries will be disabled.
77 * If we didn't pass -c, -x or -r, mark all syscalls active.
79 if ((do_specific_syscall == FALSE) && (do_exclude_syscall == FALSE) && (random_selection == FALSE) && (desired_group == GROUP_NONE))
80 mark_all_syscalls_active();
82 if (desired_group != GROUP_NONE) {
83 ret = setup_syscall_group(desired_group);
84 if (ret == FALSE)
85 return FALSE;
88 if (random_selection == TRUE)
89 enable_random_syscalls();
91 /* If we saw a '-x', set all syscalls to enabled, then selectively disable.
92 * Unless we've started enabling them already (with -r)
94 if (do_exclude_syscall == TRUE) {
95 if (random_selection == FALSE)
96 mark_all_syscalls_active();
97 deactivate_disabled_syscalls();
100 /* if we passed -n, make sure there's no VM/VFS syscalls enabled. */
101 if (no_files == TRUE)
102 disable_non_net_syscalls();
104 sanity_check_tables();
106 count_syscalls_enabled();
108 if (verbose == TRUE)
109 display_enabled_syscalls();
111 if (validate_syscall_tables() == FALSE) {
112 outputstd("No syscalls were enabled!\n");
113 outputstd("Use 32bit:%d 64bit:%d\n", use_32bit, use_64bit);
114 return FALSE;
117 return TRUE;
121 * just in case we're not using the test.sh harness, we
122 * change to the tmp dir if it exists.
124 static void change_tmp_dir(void)
126 struct stat sb;
127 const char tmpdir[]="tmp/";
128 int ret;
130 /* Check if it exists, bail early if it doesn't */
131 ret = (lstat(tmpdir, &sb));
132 if (ret == -1)
133 return;
135 /* Just in case a previous run screwed the perms. */
136 ret = chmod(tmpdir, 0755);
137 if (ret == -1)
138 output(0, "Couldn't chmod %s to 0755.\n", tmpdir);
140 ret = chdir(tmpdir);
141 if (ret == -1)
142 output(0, "Couldn't change to %s\n", tmpdir);
146 int main(int argc, char* argv[])
148 int ret = EXIT_SUCCESS;
149 int childstatus;
150 unsigned int i;
152 outputstd("Trinity v" __stringify(VERSION) " Dave Jones <davej@redhat.com>\n");
154 progname = argv[0];
156 initpid = getpid();
158 page_size = getpagesize();
159 num_online_cpus = sysconf(_SC_NPROCESSORS_ONLN);
161 select_syscall_tables();
163 if (create_shm())
164 exit(EXIT_FAILURE);
166 parse_args(argc, argv);
167 outputstd("Done parsing arguments.\n");
169 if (kernel_taint_mask != (int)0xFFFFFFFF) {
170 outputstd("Custom kernel taint mask has been specified: 0x%08x (%d).\n", kernel_taint_mask, kernel_taint_mask);
173 setup_shm_postargs();
175 if (logging == TRUE)
176 open_logfiles();
178 if (munge_tables() == FALSE) {
179 ret = EXIT_FAILURE;
180 goto out;
183 if (show_syscall_list == TRUE) {
184 dump_syscall_tables();
185 goto out;
188 init_syscalls();
190 if (show_ioctl_list == TRUE) {
191 dump_ioctls();
192 goto out;
195 if (getuid() == 0) {
196 if (dangerous == TRUE) {
197 outputstd("DANGER: RUNNING AS ROOT.\n");
198 outputstd("Unless you are running in a virtual machine, this could cause serious problems such as overwriting CMOS\n");
199 outputstd("or similar which could potentially make this machine unbootable without a firmware reset.\n\n");
200 outputstd("ctrl-c now unless you really know what you are doing.\n");
201 for (i = 10; i > 0; i--) {
202 outputstd("Continuing in %d seconds.\r", i);
203 (void)fflush(stdout);
204 sleep(1);
206 } else {
207 outputstd("Don't run as root (or pass --dangerous if you know what you are doing).\n");
208 exit(EXIT_FAILURE);
212 if (do_specific_proto == TRUE)
213 find_specific_proto(specific_proto_optarg);
215 init_buffers();
217 parse_devices();
219 pids_init();
221 setup_main_signals();
223 kernel_taint_initial = check_tainted();
224 if (kernel_taint_initial != 0) {
225 output(0, "Kernel was tainted on startup. Will ignore flags that are already set.\n");
228 change_tmp_dir();
230 /* check if we ctrl'c or something went wrong during init. */
231 if (shm->exit_reason != STILL_RUNNING)
232 goto cleanup_fds;
234 init_watchdog();
236 do_main_loop();
238 /* Shutting down. */
239 waitpid(watchdog_pid, &childstatus, 0);
241 output(0, "\nRan %ld syscalls. Successes: %ld Failures: %ld\n",
242 shm->total_syscalls_done - 1, shm->successes, shm->failures);
244 ret = EXIT_SUCCESS;
246 cleanup_fds:
248 close_sockets();
250 destroy_global_mappings();
252 if (logging == TRUE)
253 close_logfiles();
255 out:
257 exit(ret);