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); }
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; }
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; }
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; }
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; }
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; }