Ejemplo n.º 1
0
void deactivate_disabled_syscalls_uniarch(void)
{
	unsigned int i;

	for_each_syscall(i) {
		if (syscalls[i].entry->flags & TO_BE_DEACTIVATED) {
			syscalls[i].entry->flags &= ~(ACTIVE|TO_BE_DEACTIVATED);
			deactivate_syscall(i);
			output(0, "Marked syscall %s (%d) as deactivated.\n",
			syscalls[i].entry->name, syscalls[i].entry->number);
		}
	}
}
Ejemplo n.º 2
0
/*
 * This routine does 32 bit syscalls on 64 bit kernel.
 * 32-on-32 will just use syscall() directly from do_syscall() because do32bit flag is biarch only.
 */
static long syscall32(unsigned int call,
	unsigned long a1, unsigned long a2, unsigned long a3,
	unsigned long a4, unsigned long a5, unsigned long a6)
{
	long __res = 0;

#if defined(DO_32_SYSCALL)
	/* If we have CONFIG_IA32_EMULATION unset, we will segfault.
	 * Detect this case, and force 64-bit only.
	 */
	if (shm->syscalls32_succeeded == FALSE) {
		if (shm->syscalls32_attempted >= (max_children * 2)) {
			unsigned int i;

			lock(&shm->syscalltable_lock);

			/* check another thread didn't already do this. */
			if (shm->nr_active_32bit_syscalls == 0)
				goto already_done;

			output(0, "Tried %d 32-bit syscalls unsuccessfully. Disabling all 32-bit syscalls.\n",
					shm->syscalls32_attempted);

			for (i = 0; i < max_nr_32bit_syscalls; i++) {
				struct syscallentry *entry = syscalls[i].entry;

				if (entry->active_number != 0)
					deactivate_syscall(i, TRUE);
			}
already_done:
			unlock(&shm->syscalltable_lock);
		}

		shm->syscalls32_attempted++;
	}

	DO_32_SYSCALL

	if ((unsigned long)(__res) >= (unsigned long)(-133)) {
		errno = -(__res);
		__res = -1;
	}

	shm->syscalls32_succeeded = TRUE;

#else
	#error Implement 32-on-64 syscall macro for this architecture.
#endif
	return __res;
}
Ejemplo n.º 3
0
/*
 * If the syscall doesn't exist don't bother calling it next time.
 * Some syscalls return ENOSYS depending on their arguments, we mark
 * those as IGNORE_ENOSYS and keep calling them.
 */
static void deactivate_enosys(struct syscallrecord *rec, struct syscallentry *entry, unsigned int call)
{
	/* some syscalls return ENOSYS instead of EINVAL etc (futex for eg) */
	if (entry->flags & IGNORE_ENOSYS)
		return;

	lock(&shm->syscalltable_lock);

	/* check another thread didn't already do this. */
	if (entry->active_number == 0)
		goto already_done;

	output(1, "%s (%d%s) returned ENOSYS, marking as inactive.\n",
		entry->name,
		call + SYSCALL_OFFSET,
		rec->do32bit == TRUE ? ":[32BIT]" : "");

	deactivate_syscall(call, rec->do32bit);
already_done:
	unlock(&shm->syscalltable_lock);
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
int child_random_syscalls(int childno)
{
    int ret;
    unsigned int syscallnr;

    ret = sigsetjmp(ret_jump, 1);
    if (ret != 0) {
        if (handle_sigreturn(childno) == 0)
            return 0;
        ret = 0;
    }

    while (shm->exit_reason == STILL_RUNNING) {

        check_parent_pid();

        while (shm->regenerating == TRUE)
            sleep(1);

        /* If the parent reseeded, we should reflect the latest seed too. */
        if (shm->seed != shm->seeds[childno])
            set_seed(childno);

        choose_syscall_table(childno);

        if (nr_active_syscalls == 0) {
            shm->exit_reason = EXIT_NO_SYSCALLS_ENABLED;
            goto out;
        }

        if (shm->exit_reason != STILL_RUNNING)
            goto out;

        syscallnr = rand() % nr_active_syscalls;
        /* If we got a syscallnr which is not actvie repeat the attempt, since another child has switched that syscall off already.*/
        if (active_syscalls[syscallnr] == 0)
            continue;

        syscallnr = active_syscalls[syscallnr] - 1;

        if (validate_specific_syscall_silent(syscalls, syscallnr) == FALSE) {
            if (biarch == FALSE) {
                deactivate_syscall(syscallnr);
            } else {
                if (shm->do32bit[childno] == TRUE)
                    deactivate_syscall32(syscallnr);
                else
                    deactivate_syscall64(syscallnr);
            }
            continue;
        }

        shm->syscallno[childno] = syscallnr;

        if (syscalls_todo) {
            if (shm->total_syscalls_done >= syscalls_todo) {
                output(0, "Reached maximum syscall count (todo = %d, done = %d), exiting...\n",
                       syscalls_todo, shm->total_syscalls_done);
                shm->exit_reason = EXIT_REACHED_COUNT;
            }
        }

        ret = mkcall(childno);
    }
out:
    return ret;
}