Loading...
#include <stdlib.h> #include <unistd.h> #include <signal.h> #include <setjmp.h> #include <sys/types.h> #include <sys/sysctl.h> #include <sys/code_signing.h> #include <darwintest.h> static char *heap; static volatile int pass; static sigjmp_buf jbuf; static bool code_signing_monitor_enabled(void) { code_signing_config_t cs_config = 0; size_t cs_config_size = sizeof(cs_config); // Query the code signing configuration information (void)sysctlbyname("security.codesigning.config", &cs_config, &cs_config_size, NULL, 0); if (cs_config & (code_signing_config_t)CS_CONFIG_CSM_ENABLED) { return true; } return false; } static void __dead2 action(int signo, struct __siginfo *info, void *uap __attribute__((unused))) { if (info) { pass = (signo == SIGBUS && info->si_addr == heap); } siglongjmp(jbuf, 0); } T_DECL(nxheap, "Non-executable heap", T_META_CHECK_LEAKS(false), T_META_ASROOT(true)) { struct sigaction sa = { .__sigaction_u.__sa_sigaction = action, .sa_flags = SA_SIGINFO, }; // When the code-signing-monitor is enabled, any kind of executable // fault results in a direct SIGKILL. Given that, attempting to run // this test will cause a failure when the monitor is enabled. if (code_signing_monitor_enabled() == true) { T_SKIP("skipping test as code-signing-monitor is enabled"); } T_ASSERT_POSIX_ZERO(sigaction(SIGBUS, &sa, NULL), NULL); if (sigsetjmp(jbuf, 0)) { T_PASS("SIGBUS"); T_END; } T_QUIET; T_ASSERT_NOTNULL((heap = malloc(1)), NULL); *heap = (char)0xc3; // retq ((void (*)(void))heap)(); // call *%eax T_FAIL("SIGBUS"); } |