Changeset View
Changeset View
Standalone View
Standalone View
head/tests/sys/kern/ptrace_test.c
Show All 24 Lines | |||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <sys/cpuset.h> | #include <sys/cpuset.h> | ||||
#include <sys/event.h> | #include <sys/event.h> | ||||
#include <sys/file.h> | |||||
#include <sys/time.h> | #include <sys/time.h> | ||||
#include <sys/procctl.h> | #include <sys/procctl.h> | ||||
#include <sys/ptrace.h> | #include <sys/ptrace.h> | ||||
#include <sys/queue.h> | #include <sys/queue.h> | ||||
#include <sys/runq.h> | #include <sys/runq.h> | ||||
#include <sys/syscall.h> | #include <sys/syscall.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/user.h> | #include <sys/user.h> | ||||
▲ Show 20 Lines • Show All 2,979 Lines • ▼ Show 20 Lines | ATF_TC_BODY(ptrace__event_mask_sigkill_discard, tc) | ||||
ATF_REQUIRE(WIFEXITED(status)); | ATF_REQUIRE(WIFEXITED(status)); | ||||
ATF_REQUIRE(WEXITSTATUS(status) == 0); | ATF_REQUIRE(WEXITSTATUS(status) == 0); | ||||
wpid = wait(&status); | wpid = wait(&status); | ||||
ATF_REQUIRE(wpid == -1); | ATF_REQUIRE(wpid == -1); | ||||
ATF_REQUIRE(errno == ECHILD); | ATF_REQUIRE(errno == ECHILD); | ||||
} | } | ||||
static void * | |||||
flock_thread(void *arg) | |||||
{ | |||||
int fd; | |||||
fd = *(int *)arg; | |||||
(void)flock(fd, LOCK_EX); | |||||
(void)flock(fd, LOCK_UN); | |||||
return (NULL); | |||||
} | |||||
/* | |||||
* Verify that PT_ATTACH will suspend threads sleeping in an SBDRY section. | |||||
* We rely on the fact that the lockf implementation sets SBDRY before blocking | |||||
* on a lock. This is a regression test for r318191. | |||||
*/ | |||||
ATF_TC_WITHOUT_HEAD(ptrace__PT_ATTACH_with_SBDRY_thread); | |||||
ATF_TC_BODY(ptrace__PT_ATTACH_with_SBDRY_thread, tc) | |||||
{ | |||||
pthread_barrier_t barrier; | |||||
pthread_barrierattr_t battr; | |||||
char tmpfile[64]; | |||||
pid_t child, wpid; | |||||
int error, fd, i, status; | |||||
ATF_REQUIRE(pthread_barrierattr_init(&battr) == 0); | |||||
ATF_REQUIRE(pthread_barrierattr_setpshared(&battr, | |||||
PTHREAD_PROCESS_SHARED) == 0); | |||||
ATF_REQUIRE(pthread_barrier_init(&barrier, &battr, 2) == 0); | |||||
(void)snprintf(tmpfile, sizeof(tmpfile), "./ptrace.XXXXXX"); | |||||
fd = mkstemp(tmpfile); | |||||
ATF_REQUIRE(fd >= 0); | |||||
ATF_REQUIRE((child = fork()) != -1); | |||||
if (child == 0) { | |||||
pthread_t t[2]; | |||||
int error, cfd; | |||||
error = pthread_barrier_wait(&barrier); | |||||
if (error != 0 && error != PTHREAD_BARRIER_SERIAL_THREAD) | |||||
_exit(1); | |||||
cfd = open(tmpfile, O_RDONLY); | |||||
if (cfd < 0) | |||||
_exit(1); | |||||
/* | |||||
* We want at least two threads blocked on the file lock since | |||||
* the SIGSTOP from PT_ATTACH may kick one of them out of | |||||
* sleep. | |||||
*/ | |||||
if (pthread_create(&t[0], NULL, flock_thread, &cfd) != 0) | |||||
_exit(1); | |||||
if (pthread_create(&t[1], NULL, flock_thread, &cfd) != 0) | |||||
_exit(1); | |||||
if (pthread_join(t[0], NULL) != 0) | |||||
_exit(1); | |||||
if (pthread_join(t[1], NULL) != 0) | |||||
_exit(1); | |||||
_exit(0); | |||||
} | |||||
ATF_REQUIRE(flock(fd, LOCK_EX) == 0); | |||||
error = pthread_barrier_wait(&barrier); | |||||
ATF_REQUIRE(error == 0 || error == PTHREAD_BARRIER_SERIAL_THREAD); | |||||
/* | |||||
* Give the child some time to block. Is there a better way to do this? | |||||
*/ | |||||
sleep(1); | |||||
/* | |||||
* Attach and give the child 3 seconds to stop. | |||||
*/ | |||||
ATF_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) == 0); | |||||
for (i = 0; i < 3; i++) { | |||||
wpid = waitpid(child, &status, WNOHANG); | |||||
if (wpid == child && WIFSTOPPED(status) && | |||||
WSTOPSIG(status) == SIGSTOP) | |||||
break; | |||||
sleep(1); | |||||
} | |||||
ATF_REQUIRE_MSG(i < 3, "failed to stop child process after PT_ATTACH"); | |||||
ATF_REQUIRE(ptrace(PT_DETACH, child, NULL, 0) == 0); | |||||
ATF_REQUIRE(flock(fd, LOCK_UN) == 0); | |||||
ATF_REQUIRE(unlink(tmpfile) == 0); | |||||
ATF_REQUIRE(close(fd) == 0); | |||||
} | |||||
ATF_TP_ADD_TCS(tp) | ATF_TP_ADD_TCS(tp) | ||||
{ | { | ||||
ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_trace_me); | ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_trace_me); | ||||
ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_attach); | ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_attach); | ||||
ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_child_debugger); | ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_child_debugger); | ||||
ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_unrelated_debugger); | ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_unrelated_debugger); | ||||
ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached); | ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached); | ||||
Show All 31 Lines | #endif | ||||
ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_change_sig); | ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_change_sig); | ||||
ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_sigtrap_system_call_entry); | ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_sigtrap_system_call_entry); | ||||
ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_mix); | ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_mix); | ||||
ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_kqueue); | ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_kqueue); | ||||
ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_thread_sigmask); | ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_with_signal_thread_sigmask); | ||||
ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop1); | ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop1); | ||||
ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop2); | ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop2); | ||||
ATF_TP_ADD_TC(tp, ptrace__event_mask_sigkill_discard); | ATF_TP_ADD_TC(tp, ptrace__event_mask_sigkill_discard); | ||||
ATF_TP_ADD_TC(tp, ptrace__PT_ATTACH_with_SBDRY_thread); | |||||
return (atf_no_error()); | return (atf_no_error()); | ||||
} | } |