예제 #1
0
void child(int cpu)
{
	cpu_set_t set;

	CPU_ZERO(&set);
	CPU_SET(cpu, &set);
	if (sched_setaffinity(0, sizeof(set), &set) != 0) {
		ksft_print_msg("sched_setaffinity() failed: %s\n",
			strerror(errno));
		_exit(1);
	}

	if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) != 0) {
		ksft_print_msg("ptrace(PTRACE_TRACEME) failed: %s\n",
			strerror(errno));
		_exit(1);
	}

	if (raise(SIGSTOP) != 0) {
		ksft_print_msg("raise(SIGSTOP) failed: %s\n", strerror(errno));
		_exit(1);
	}

	_exit(0);
}
예제 #2
0
int main(int argc, char *argv[])
{
	int c, ret;

	while ((c = getopt(argc, argv, "bchlot:v:")) != -1) {
		switch (c) {
		case 'b':
			broadcast = 1;
			break;
		case 'c':
			log_color(1);
			break;
		case 'h':
			usage(basename(argv[0]));
			exit(0);
		case 'l':
			locked = 1;
			break;
		case 'o':
			owner = 1;
			locked = 0;
			break;
		case 't':
			timeout_ns = atoi(optarg);
			break;
		case 'v':
			log_verbosity(atoi(optarg));
			break;
		default:
			usage(basename(argv[0]));
			exit(1);
		}
	}

	ksft_print_header();
	ksft_print_msg("%s: Test requeue functionality\n", basename(argv[0]));
	ksft_print_msg(
		"\tArguments: broadcast=%d locked=%d owner=%d timeout=%ldns\n",
		broadcast, locked, owner, timeout_ns);

	/*
	 * FIXME: unit_test is obsolete now that we parse options and the
	 * various style of runs are done by run.sh - simplify the code and move
	 * unit_test into main()
	 */
	ret = unit_test(broadcast, locked, owner, timeout_ns);

	print_result(TEST_NAME, ret);
	return ret;
}
예제 #3
0
int main(int argc, char **argv)
{
	const char *atsec = "";

	/*
	 * Be careful just in case a setgid or setcapped copy of this
	 * helper gets out.
	 */

	if (argc != 5)
		ksft_exit_fail_msg("wrong argc\n");

#ifdef HAVE_GETAUXVAL
	if (getauxval(AT_SECURE))
		atsec = " (AT_SECURE is set)";
	else
		atsec = " (AT_SECURE is not set)";
#endif

	capng_get_caps_process();

	if (capng_have_capability(CAPNG_EFFECTIVE, CAP_NET_BIND_SERVICE) != bool_arg(argv, 1)) {
		ksft_print_msg("Wrong effective state%s\n", atsec);
		return 1;
	}

	if (capng_have_capability(CAPNG_PERMITTED, CAP_NET_BIND_SERVICE) != bool_arg(argv, 2)) {
		ksft_print_msg("Wrong permitted state%s\n", atsec);
		return 1;
	}

	if (capng_have_capability(CAPNG_INHERITABLE, CAP_NET_BIND_SERVICE) != bool_arg(argv, 3)) {
		ksft_print_msg("Wrong inheritable state%s\n", atsec);
		return 1;
	}

	if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_NET_BIND_SERVICE, 0, 0, 0) != bool_arg(argv, 4)) {
		ksft_print_msg("Wrong ambient state%s\n", atsec);
		return 1;
	}

	ksft_print_msg("%s: Capabilities after execve were correct\n",
			"validate_cap:");
	return 0;
}
예제 #4
0
int main(int argc, char **argv)
{
	pthread_t thr;
	int ret = RET_PASS;
	int res;
	int c;

	while ((c = getopt(argc, argv, "chv:")) != -1) {
		switch (c) {
		case 'c':
			log_color(1);
			break;
		case 'h':
			usage(basename(argv[0]));
			exit(0);
		case 'v':
			log_verbosity(atoi(optarg));
			break;
		default:
			usage(basename(argv[0]));
			exit(1);
		}
	}

	ksft_print_header();
	ksft_set_plan(1);
	ksft_print_msg(
		"%s: Test the futex value of private file mappings in FUTEX_WAIT\n",
		basename(argv[0]));

	ret = pthread_create(&thr, NULL, thr_futex_wait, NULL);
	if (ret < 0) {
		fprintf(stderr, "pthread_create error\n");
		ret = RET_ERROR;
		goto out;
	}

	info("wait a while\n");
	usleep(WAKE_WAIT_US);
	val = 2;
	res = futex_wake(&val, 1, 0);
	info("futex_wake %d\n", res);
	if (res != 1) {
		fail("FUTEX_WAKE didn't find the waiting thread.\n");
		ret = RET_FAIL;
	}

	info("join\n");
	pthread_join(thr, NULL);

 out:
	print_result(TEST_NAME, ret);
	return ret;
}
int main(int argc, char *argv[])
{
	unsigned int old_val;
	struct sigaction sa;
	pthread_t waiter;
	int c, res, ret = RET_PASS;

	while ((c = getopt(argc, argv, "chv:")) != -1) {
		switch (c) {
		case 'c':
			log_color(1);
			break;
		case 'h':
			usage(basename(argv[0]));
			exit(0);
		case 'v':
			log_verbosity(atoi(optarg));
			break;
		default:
			usage(basename(argv[0]));
			exit(1);
		}
	}

	ksft_print_header();
	ksft_set_plan(1);
	ksft_print_msg("%s: Test signal handling during requeue_pi\n",
	       basename(argv[0]));
	ksft_print_msg("\tArguments: <none>\n");

	sa.sa_handler = handle_signal;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;
	if (sigaction(SIGUSR1, &sa, NULL)) {
		error("sigaction\n", errno);
		exit(1);
	}

	info("m1:f2: %x\n", f2);
	info("Creating waiter\n");
	res = create_rt_thread(&waiter, waiterfn, NULL, SCHED_FIFO, 1);
	if (res) {
		error("Creating waiting thread failed", res);
		ret = RET_ERROR;
		goto out;
	}

	info("Calling FUTEX_LOCK_PI on f2=%x @ %p\n", f2, &f2);
	info("m2:f2: %x\n", f2);
	futex_lock_pi(&f2, 0, 0, FUTEX_PRIVATE_FLAG);
	info("m3:f2: %x\n", f2);

	while (1) {
		/*
		 * signal the waiter before requeue, waiter should automatically
		 * restart futex_wait_requeue_pi() in the kernel. Wait for the
		 * waiter to block on f1 again.
		 */
		info("Issuing SIGUSR1 to waiter\n");
		pthread_kill(waiter, SIGUSR1);
		usleep(DELAY_US);

		info("Requeueing waiter via FUTEX_CMP_REQUEUE_PI\n");
		old_val = f1;
		res = futex_cmp_requeue_pi(&f1, old_val, &(f2), 1, 0,
					   FUTEX_PRIVATE_FLAG);
		/*
		 * If res is non-zero, we either requeued the waiter or hit an
		 * error, break out and handle it. If it is zero, then the
		 * signal may have hit before the the waiter was blocked on f1.
		 * Try again.
		 */
		if (res > 0) {
			atomic_set(&requeued, 1);
			break;
		} else if (res < 0) {
			error("FUTEX_CMP_REQUEUE_PI failed\n", errno);
			ret = RET_ERROR;
			break;
		}
	}
	info("m4:f2: %x\n", f2);

	/*
	 * Signal the waiter after requeue, waiter should return from
	 * futex_wait_requeue_pi() with EWOULDBLOCK. Join the thread here so the
	 * futex_unlock_pi() can't happen before the signal wakeup is detected
	 * in the kernel.
	 */
	info("Issuing SIGUSR1 to waiter\n");
	pthread_kill(waiter, SIGUSR1);
	info("Waiting for waiter to return\n");
	pthread_join(waiter, NULL);

	info("Calling FUTEX_UNLOCK_PI on mutex=%x @ %p\n", f2, &f2);
	futex_unlock_pi(&f2, FUTEX_PRIVATE_FLAG);
	info("m5:f2: %x\n", f2);

 out:
	if (ret == RET_PASS && waiter_ret)
		ret = waiter_ret;

	print_result(TEST_NAME, ret);
	return ret;
}
예제 #6
0
파일: pidfd_test.c 프로젝트: avagin/linux
static int test_pidfd_send_signal_recycled_pid_fail(void)
{
	int i, ret;
	pid_t pid1;
	const char *test_name = "pidfd_send_signal signal recycled pid";

	ret = unshare(CLONE_NEWPID);
	if (ret < 0)
		ksft_exit_fail_msg("%s test: Failed to unshare pid namespace\n",
				   test_name);

	ret = unshare(CLONE_NEWNS);
	if (ret < 0)
		ksft_exit_fail_msg(
			"%s test: Failed to unshare mount namespace\n",
			test_name);

	ret = mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0);
	if (ret < 0)
		ksft_exit_fail_msg("%s test: Failed to remount / private\n",
				   test_name);

	/* pid 1 in new pid namespace */
	pid1 = fork();
	if (pid1 < 0)
		ksft_exit_fail_msg("%s test: Failed to create new process\n",
				   test_name);

	if (pid1 == 0) {
		char buf[256];
		pid_t pid2;
		int pidfd = -1;

		(void)umount2("/proc", MNT_DETACH);
		ret = mount("proc", "/proc", "proc", 0, NULL);
		if (ret < 0)
			_exit(PIDFD_ERROR);

		/* grab pid PID_RECYCLE */
		for (i = 0; i <= PIDFD_MAX_DEFAULT; i++) {
			pid2 = fork();
			if (pid2 < 0)
				_exit(PIDFD_ERROR);

			if (pid2 == 0)
				_exit(PIDFD_PASS);

			if (pid2 == PID_RECYCLE) {
				snprintf(buf, sizeof(buf), "/proc/%d", pid2);
				ksft_print_msg("pid to recycle is %d\n", pid2);
				pidfd = open(buf, O_DIRECTORY | O_CLOEXEC);
			}

			if (wait_for_pid(pid2))
				_exit(PIDFD_ERROR);

			if (pid2 >= PID_RECYCLE)
				break;
		}

		/*
		 * We want to be as predictable as we can so if we haven't been
		 * able to grab pid PID_RECYCLE skip the test.
		 */
		if (pid2 != PID_RECYCLE) {
			/* skip test */
			close(pidfd);
			_exit(PIDFD_SKIP);
		}

		if (pidfd < 0)
			_exit(PIDFD_ERROR);

		for (i = 0; i <= PIDFD_MAX_DEFAULT; i++) {
			char c;
			int pipe_fds[2];
			pid_t recycled_pid;
			int child_ret = PIDFD_PASS;

			ret = pipe2(pipe_fds, O_CLOEXEC);
			if (ret < 0)
				_exit(PIDFD_ERROR);

			recycled_pid = fork();
			if (recycled_pid < 0)
				_exit(PIDFD_ERROR);

			if (recycled_pid == 0) {
				close(pipe_fds[1]);
				(void)read(pipe_fds[0], &c, 1);
				close(pipe_fds[0]);

				_exit(PIDFD_PASS);
			}

			/*
			 * Stop the child so we can inspect whether we have
			 * recycled pid PID_RECYCLE.
			 */
			close(pipe_fds[0]);
			ret = kill(recycled_pid, SIGSTOP);
			close(pipe_fds[1]);
			if (ret) {
				(void)wait_for_pid(recycled_pid);
				_exit(PIDFD_ERROR);
			}

			/*
			 * We have recycled the pid. Try to signal it. This
			 * needs to fail since this is a different process than
			 * the one the pidfd refers to.
			 */
			if (recycled_pid == PID_RECYCLE) {
				ret = sys_pidfd_send_signal(pidfd, SIGCONT,
							    NULL, 0);
				if (ret && errno == ESRCH)
					child_ret = PIDFD_XFAIL;
				else
					child_ret = PIDFD_FAIL;
			}

			/* let the process move on */
			ret = kill(recycled_pid, SIGCONT);
			if (ret)
				(void)kill(recycled_pid, SIGKILL);

			if (wait_for_pid(recycled_pid))
				_exit(PIDFD_ERROR);

			switch (child_ret) {
			case PIDFD_FAIL:
				/* fallthrough */
			case PIDFD_XFAIL:
				_exit(child_ret);
			case PIDFD_PASS:
				break;
			default:
				/* not reached */
				_exit(PIDFD_ERROR);
			}

			/*
			 * If the user set a custom pid_max limit we could be
			 * in the millions.
			 * Skip the test in this case.
			 */
			if (recycled_pid > PIDFD_MAX_DEFAULT)
				_exit(PIDFD_SKIP);
		}

		/* failed to recycle pid */
		_exit(PIDFD_SKIP);
	}

	ret = wait_for_pid(pid1);
	switch (ret) {
	case PIDFD_FAIL:
		ksft_exit_fail_msg(
			"%s test: Managed to signal recycled pid %d\n",
			test_name, PID_RECYCLE);
	case PIDFD_PASS:
		ksft_exit_fail_msg("%s test: Failed to recycle pid %d\n",
				   test_name, PID_RECYCLE);
	case PIDFD_SKIP:
		ksft_print_msg("%s test: Skipping test\n", test_name);
		ret = 0;
		break;
	case PIDFD_XFAIL:
		ksft_test_result_pass(
			"%s test: Failed to signal recycled pid as expected\n",
			test_name);
		ret = 0;
		break;
	default /* PIDFD_ERROR */:
		ksft_exit_fail_msg("%s test: Error while running tests\n",
				   test_name);
	}

	return ret;
}
예제 #7
0
bool run_test(int cpu)
{
	int status;
	pid_t pid = fork();
	pid_t wpid;

	if (pid < 0) {
		ksft_print_msg("fork() failed: %s\n", strerror(errno));
		return false;
	}
	if (pid == 0)
		child(cpu);

	wpid = waitpid(pid, &status, __WALL);
	if (wpid != pid) {
		ksft_print_msg("waitpid() failed: %s\n", strerror(errno));
		return false;
	}
	if (!WIFSTOPPED(status)) {
		ksft_print_msg("child did not stop: %s\n", strerror(errno));
		return false;
	}
	if (WSTOPSIG(status) != SIGSTOP) {
		ksft_print_msg("child did not stop with SIGSTOP: %s\n",
			strerror(errno));
		return false;
	}

	if (ptrace(PTRACE_SINGLESTEP, pid, NULL, NULL) < 0) {
		if (errno == EIO) {
			ksft_exit_skip(
				"ptrace(PTRACE_SINGLESTEP) not supported on this architecture: %s\n",
				strerror(errno));
		}
		ksft_print_msg("ptrace(PTRACE_SINGLESTEP) failed: %s\n",
			strerror(errno));
		return false;
	}

	wpid = waitpid(pid, &status, __WALL);
	if (wpid != pid) {
		ksft_print_msg("waitpid() failed: $s\n", strerror(errno));
		return false;
	}
	if (WIFEXITED(status)) {
		ksft_print_msg("child did not single-step: %s\n",
			strerror(errno));
		return false;
	}
	if (!WIFSTOPPED(status)) {
		ksft_print_msg("child did not stop: %s\n", strerror(errno));
		return false;
	}
	if (WSTOPSIG(status) != SIGTRAP) {
		ksft_print_msg("child did not stop with SIGTRAP: %s\n",
			strerror(errno));
		return false;
	}

	if (ptrace(PTRACE_CONT, pid, NULL, NULL) < 0) {
		ksft_print_msg("ptrace(PTRACE_CONT) failed: %s\n",
			strerror(errno));
		return false;
	}

	wpid = waitpid(pid, &status, __WALL);
	if (wpid != pid) {
		ksft_print_msg("waitpid() failed: %s\n", strerror(errno));
		return false;
	}
	if (!WIFEXITED(status)) {
		ksft_print_msg("child did not exit after PTRACE_CONT: %s\n",
			strerror(errno));
		return false;
	}

	return true;
}