static void choose_syscall_table(int childno) { if (biarch == FALSE) { active_syscalls = shm->active_syscalls; nr_active_syscalls = shm->nr_active_syscalls; } else { /* First, check that we have syscalls enabled in either table. */ if (validate_syscall_table_64() == FALSE) { use_64bit = FALSE; /* If no 64bit syscalls enabled, force 32bit. */ shm->do32bit[childno] = TRUE; } if (validate_syscall_table_32() == FALSE) use_32bit = FALSE; /* If both tables enabled, pick randomly. */ if ((use_64bit == TRUE) && (use_32bit == TRUE)) { /* * 10% possibility of a 32bit syscall */ shm->do32bit[childno] = FALSE; if (rand() % 100 < 10) shm->do32bit[childno] = TRUE; } if (shm->do32bit[childno] == FALSE) { syscalls = syscalls_64bit; nr_active_syscalls = shm->nr_active_64bit_syscalls; active_syscalls = shm->active_syscalls64; max_nr_syscalls = max_nr_64bit_syscalls; } else { syscalls = syscalls_32bit; nr_active_syscalls = shm->nr_active_32bit_syscalls; active_syscalls = shm->active_syscalls32; max_nr_syscalls = max_nr_32bit_syscalls; } } if (no_syscalls_enabled() == TRUE) { output(0, "[%d] No more syscalls enabled. Exiting\n", getpid()); shm->exit_reason = EXIT_NO_SYSCALLS_ENABLED; } }
bool child_random_syscalls(void) { struct syscallrecord *rec; unsigned int syscallnr; bool do32; unsigned int len; retry: if (no_syscalls_enabled() == TRUE) { output(0, "[%d] No more syscalls enabled. Exiting\n", getpid()); shm->exit_reason = EXIT_NO_SYSCALLS_ENABLED; return FAIL; } /* Ok, we're doing another syscall, let's pick one. */ do32 = choose_syscall_table(); syscallnr = rand() % max_nr_syscalls; /* If we got a syscallnr which is not active repeat the attempt, * since another child has switched that syscall off already.*/ if (active_syscalls[syscallnr] == 0) goto retry; syscallnr = active_syscalls[syscallnr] - 1; if (validate_specific_syscall_silent(syscalls, syscallnr) == FALSE) { deactivate_syscall(syscallnr, do32); goto retry; } rec = &this_child->syscall; /* critical section for shm updates. */ lock(&rec->lock); rec->do32bit = do32; rec->nr = syscallnr; unlock(&rec->lock); if (syscalls_todo) { if (shm->stats.total_syscalls_done >= syscalls_todo) shm->exit_reason = EXIT_REACHED_COUNT; } /* Generate arguments, print them out */ generate_syscall_args(rec); output_syscall_prefix(rec); /* Sanity check: Make sure the length of the buffer remains * constant across the syscall. */ len = strlen(rec->prebuffer); /* If we're going to pause, might as well sync pre-syscall */ if (dopause == TRUE) synclogs(); do_syscall(rec); /* post syscall sanity checks. */ if (len != strlen(rec->prebuffer)) { output(0, "Sanity check failed: prebuffer length changed from %d to %d.\n", len, strlen(rec->prebuffer)); } /* Output the syscall result, and clean up */ output_syscall_postfix(rec); if (dopause == TRUE) sleep(1); handle_syscall_ret(rec); return TRUE; }