xref: /xnu-12377.81.4/tests/test_utils.c (revision 043036a2b3718f7f0be807e2870f8f47d3fa0796)
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