예제 #1
0
/*
 *  stress_ptrace()
 *	stress ptracing
 */
int stress_ptrace(
	uint64_t *const counter,
	const uint32_t instance,
	const uint64_t max_ops,
	const char *name)
{
	pid_t pid;

	(void)instance;

	pid = fork();
	if (pid < 0) {
		pr_failed_dbg(name, "fork");
		return EXIT_FAILURE;
	} else if (pid == 0) {
		setpgid(0, pgrp);
		/*
		 * Child to be traced, we abort if we detect
		 * we are already being traced by someone else
		 * as this makes life way too complex
		 */
		if (ptrace(PTRACE_TRACEME) != 0) {
			pr_fail(stderr, "%s: ptrace child being traced "
				"already, aborting\n", name);
			_exit(0);
		}
		/* Wait for parent to start tracing me */
		kill(getpid(), SIGSTOP);

		/*
		 *  A simple mix of system calls
		 */
		while (opt_do_run) {
			(void)getppid();
			(void)getgid();
			(void)getegid();
			(void)getuid();
			(void)geteuid();
			(void)getpgrp();
			(void)time(NULL);
		}
		_exit(0);
	} else {
		/* Parent to do the tracing */
		int status;

		setpgid(pid, pgrp);

		if (waitpid(pid, &status, 0) < 0) {
			pr_failed_dbg(name, "waitpid");
			return EXIT_FAILURE;
		}
		if (ptrace(PTRACE_SETOPTIONS, pid,
			0, PTRACE_O_TRACESYSGOOD) < 0) {
			pr_failed_dbg(name, "ptrace");
			return EXIT_FAILURE;
		}

		do {
			/*
			 *  We do two of the following per syscall,
			 *  one at the start, and one at the end to catch
			 *  the return.  In this stressor we don't really
			 *  care which is which, we just care about counting
			 *  them
			 */
			if (stress_syscall_wait(name, pid))
				break;
			(*counter)++;
		} while (opt_do_run && (!max_ops || *counter < max_ops));

		/* Terminate child */
		(void)kill(pid, SIGKILL);
		if (waitpid(pid, &status, 0) < 0)
			pr_failed_dbg(name, "waitpid");
	}
	return EXIT_SUCCESS;
}
예제 #2
0
/*
 *  stress_ptrace()
 *	stress ptracing
 */
static int stress_ptrace(const args_t *args)
{
	pid_t pid;

	pid = fork();
	if (pid < 0) {
		pr_fail_dbg("fork");
		return EXIT_FAILURE;
	} else if (pid == 0) {
		(void)setpgid(0, g_pgrp);
		stress_parent_died_alarm();

		/*
		 * Child to be traced, we abort if we detect
		 * we are already being traced by someone else
		 * as this makes life way too complex
		 */
		if (ptrace(PTRACE_TRACEME) != 0) {
			pr_fail("%s: ptrace child being traced "
				"already, aborting\n", args->name);
			_exit(0);
		}
		/* Wait for parent to start tracing me */
		(void)kill(getpid(), SIGSTOP);

		/*
		 *  A simple mix of system calls
		 */
		while (g_keep_stressing_flag) {
			pid_t pidtmp;
			gid_t gidtmp;
			uid_t uidtmp;
			time_t ttmp;

			pidtmp = getppid();
			(void)pidtmp;

#if defined(HAVE_GETPGRP)
			pidtmp = getpgrp();
			(void)pidtmp;
#endif

			gidtmp = getgid();
			(void)gidtmp;

			gidtmp = getegid();
			(void)gidtmp;

			uidtmp = getuid();
			(void)uidtmp;

			uidtmp = geteuid();
			(void)uidtmp;

			ttmp = time(NULL);
			(void)ttmp;
		}
		_exit(0);
	} else {
		/* Parent to do the tracing */
		int status;

		(void)setpgid(pid, g_pgrp);

		if (shim_waitpid(pid, &status, 0) < 0) {
			if (errno != EINTR) {
				pr_fail_dbg("waitpid");
				return EXIT_FAILURE;
			}
			return EXIT_SUCCESS;
		}
		if (ptrace(PTRACE_SETOPTIONS, pid,
			0, PTRACE_O_TRACESYSGOOD) < 0) {
			pr_fail_dbg("ptrace");
			return EXIT_FAILURE;
		}

		do {
			/*
			 *  We do two of the following per syscall,
			 *  one at the start, and one at the end to catch
			 *  the return.  In this stressor we don't really
			 *  care which is which, we just care about counting
			 *  them
			 */
			if (stress_syscall_wait(args, pid))
				break;
			inc_counter(args);
		} while (keep_stressing());

		/* Terminate child */
		(void)kill(pid, SIGKILL);
		if (shim_waitpid(pid, &status, 0) < 0)
			pr_fail_dbg("waitpid");
	}
	return EXIT_SUCCESS;
}