1 #include <dispatch/dispatch.h>
2 #include <mach-o/dyld.h>
3 #include <signal.h>
4 #include <sys/code_signing.h>
5 #include <sys/kern_sysctl.h>
6 #include <sys/sysctl.h>
7 #include <sys/kern_memorystatus.h>
8
9 #include <darwintest.h>
10 #include <darwintest_utils.h>
11
12 #include "test_utils.h"
13
14 bool
is_development_kernel(void)15 is_development_kernel(void)
16 {
17 static dispatch_once_t is_development_once;
18 static bool is_development;
19
20 dispatch_once(&is_development_once, ^{
21 int dev;
22 size_t dev_size = sizeof(dev);
23
24 T_QUIET;
25 T_ASSERT_POSIX_SUCCESS(sysctlbyname("kern.development", &dev,
26 &dev_size, NULL, 0), NULL);
27 is_development = (dev != 0);
28 });
29
30 return is_development;
31 }
32
33 bool
is_sptm_enabled(void)34 is_sptm_enabled(void)
35 {
36 static dispatch_once_t is_sptm_enabled_once;
37 static bool is_sptm_enabled;
38
39 dispatch_once(&is_sptm_enabled_once, ^{
40 int page_protection_type;
41 size_t size = sizeof(page_protection_type);
42 int err = sysctlbyname("kern.page_protection_type", &page_protection_type, &size, NULL, 0);
43 T_ASSERT_POSIX_SUCCESS(err, "sysctl(\"kern.page_protection_type\");");
44 is_sptm_enabled = (page_protection_type == 2);
45 });
46
47 return is_sptm_enabled;
48 }
49
50 bool
is_map_jit_allowed(void)51 is_map_jit_allowed(void)
52 {
53 static dispatch_once_t is_map_jit_allowed_once;
54 static bool is_map_jit_allowed;
55
56 dispatch_once(&is_map_jit_allowed_once, ^{
57 code_signing_config_t cs_config = 0;
58 size_t cs_config_size = sizeof(cs_config);
59
60 /* Query the code signing configuration information */
61 int err = sysctlbyname("security.codesigning.config", &cs_config, &cs_config_size, NULL, 0);
62 T_ASSERT_POSIX_SUCCESS(err, "sysctl(\"security.codesigning.config\");");
63
64 is_map_jit_allowed = !!(cs_config & CS_CONFIG_MAP_JIT);
65 });
66
67 return is_map_jit_allowed;
68 }
69
70 bool
process_is_translated()71 process_is_translated()
72 {
73 static dispatch_once_t is_translated_once;
74 static bool is_translated;
75
76 dispatch_once(&is_translated_once, ^{
77 int out_value = 0;
78 size_t inout_size = sizeof(out_value);
79 if (sysctlbyname("sysctl.proc_translated", &out_value, &inout_size, NULL, 0) != 0) {
80 /*
81 * ENOENT means the sysctl is not present and therefore
82 * this process is not translated. Any other error is bad.
83 */
84 T_QUIET; T_ASSERT_POSIX_ERROR(errno, ENOENT, "sysctlbyname(sysctl.proc_translated)");
85 is_translated = false;
86 } else {
87 T_QUIET; T_ASSERT_GE(inout_size, sizeof(out_value), "sysctlbyname(sysctl.proc_translated)");
88 is_translated = (bool)out_value;
89 }
90 });
91 return is_translated;
92 }
93
94
95 pid_t
launch_background_helper(const char * variant,bool start_suspended,bool memorystatus_managed)96 launch_background_helper(
97 const char* variant,
98 bool start_suspended,
99 bool memorystatus_managed)
100 {
101 pid_t pid;
102 char **launch_tool_args;
103 char testpath[PATH_MAX];
104 char *variant_cpy = strdup(variant);
105 uint32_t testpath_buf_size;
106 int ret;
107
108 testpath_buf_size = sizeof(testpath);
109 ret = _NSGetExecutablePath(testpath, &testpath_buf_size);
110 launch_tool_args = (char *[]){
111 testpath,
112 "-n",
113 variant_cpy,
114 NULL
115 };
116 ret = dt_launch_tool(&pid, launch_tool_args, start_suspended, NULL, NULL);
117 if (ret != 0) {
118 T_LOG("dt_launch tool returned %d with error code %d", ret, errno);
119 }
120 T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "dt_launch_tool");
121 if (memorystatus_managed) {
122 set_process_memorystatus_managed(pid);
123 }
124 free(variant_cpy);
125 return pid;
126 }
127
128 void
set_process_memorystatus_managed(pid_t pid)129 set_process_memorystatus_managed(pid_t pid)
130 {
131 kern_return_t ret = memorystatus_control(MEMORYSTATUS_CMD_SET_PROCESS_IS_MANAGED, pid, 1, NULL, 0);
132 T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "memorystatus_control");
133 }
134