pthread_jit_write_protection.c [plain text]
#include <darwintest.h>
#include <darwintest_perf.h>
#include "pthread_jit_write_test_inline.h"
T_GLOBAL_META(T_META_RUN_CONCURRENTLY(true));
static void *
expect_write_fail_thread(__unused void * arg)
{
fault_state_create();
if (does_access_fault(ACCESS_WRITE, rwx_addr)) {
pthread_exit((void *)0);
} else {
pthread_exit((void *)1);
}
}
T_DECL(pthread_jit_write_protect,
"Verify that the pthread_jit_write_protect interfaces work correctly")
{
void * join_value = NULL;
pthread_t pthread;
bool expect_fault = pthread_jit_write_protect_supported_np();
pthread_jit_test_setup();
pthread_jit_write_protect_np(FALSE);
T_EXPECT_EQ(does_access_fault(ACCESS_WRITE, rwx_addr), 0, "Write with RWX->RW");
pthread_jit_write_protect_np(TRUE);
T_EXPECT_EQ(does_access_fault(ACCESS_EXECUTE, rwx_addr), 0, "Execute with RWX->RX");
pthread_jit_write_protect_np(TRUE);
T_EXPECT_EQ(does_access_fault(ACCESS_WRITE, rwx_addr), expect_fault, "Write with RWX->RX");
pthread_jit_write_protect_np(FALSE);
T_EXPECT_EQ(does_access_fault(ACCESS_EXECUTE, rwx_addr), expect_fault, "Execute with RWX->RW");
pthread_jit_write_protect_np(FALSE);
if (expect_fault) {
T_SETUPBEGIN;
T_ASSERT_POSIX_ZERO(pthread_create(&pthread, NULL, expect_write_fail_thread, NULL), "pthread_create expect_write_fail_thread");
T_ASSERT_POSIX_ZERO(pthread_join(pthread, &join_value), "pthread_join expect_write_fail_thread");
T_SETUPEND;
T_ASSERT_NULL((join_value), "Write on other thread with RWX->RX, "
"RWX->RW on parent thread");
}
pthread_jit_test_teardown();
}
T_DECL(thread_self_restrict_rwx_perf,
"Test the performance of the thread_self_restrict_rwx interfaces",
T_META_TAG_PERF, T_META_CHECK_LEAKS(false))
{
dt_stat_time_t dt_stat_time;
dt_stat_time = dt_stat_time_create("rx->rw->rx time");
T_STAT_MEASURE_LOOP(dt_stat_time) {
pthread_jit_write_protect_np(FALSE);
pthread_jit_write_protect_np(TRUE);
}
dt_stat_finalize(dt_stat_time);
}