1 /*
2 * Copyright (c) 2000-2024 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #include "mock_misc.h"
30 #include "std_safe.h"
31 #include "unit_test_utils.h"
32 #include "dt_proxy.h"
33
34 #include "fibers/random.h"
35
36 #include <kern/btlog.h>
37 #include <mach/vm_types.h>
38 #include <vm/vm_sanitize_telemetry.h>
39
40 // This initialized the darwintest asserts proxies in the mocks .dylib
41 struct dt_proxy_callbacks *dt_proxy = NULL;
42 void
set_dt_proxy_mock(struct dt_proxy_callbacks * p)43 set_dt_proxy_mock(struct dt_proxy_callbacks *p)
44 {
45 dt_proxy = p;
46 }
47 struct dt_proxy_callbacks *
get_dt_proxy_mock(void)48 get_dt_proxy_mock(void)
49 {
50 return dt_proxy;
51 }
52
53
54 // for cpu_data_startup_init
55 T_MOCK(unsigned int,
56 ml_get_cpu_count, (void))
57 {
58 return 1;
59 }
60
61 T_MOCK(vm_offset_t,
62 min_valid_stack_address, (void))
63 {
64 return 0;
65 }
66
67 T_MOCK(vm_offset_t,
68 max_valid_stack_address, (void))
69 {
70 return 0;
71 }
72
73 T_MOCK(u_int32_t,
74 RandomULong, (void))
75 {
76 return (u_int32_t)random_next();
77 }
78
79 T_MOCK(uint64_t,
80 early_random, (void))
81 {
82 return random_next();
83 }
84
85 // needed because in-kernel impl for some reason got to libcorecrypt dyld
86 T_MOCK(void,
87 read_erandom, (void * buffer, unsigned int numBytes))
88 {
89 unsigned char *cbuf = (unsigned char *)buffer;
90 for (int i = 0; i < numBytes; ++i) {
91 cbuf[i] = (unsigned char)(random_next() % 0xFF);
92 }
93 }
94
95 T_MOCK(void,
96 read_random, (void * buffer, unsigned int numbytes))
97 {
98 read_erandom(buffer, numbytes);
99 }
100
101 T_MOCK(uint32_t,
102 PE_get_random_seed, (unsigned char *dst_random_seed, uint32_t request_size))
103 {
104 for (uint32_t i = 0; i < request_size; i++, dst_random_seed++) {
105 *dst_random_seed = 0;
106 }
107 return request_size;
108 }
109
110 T_MOCK(bool,
111 ml_unsafe_kernel_text, (void))
112 {
113 return true;
114 }
115
116
117 T_MOCK(__attribute__((noinline, not_tail_called)) void,
118 os_log_with_args, (void* oslog, uint8_t type, const char *fmt, va_list args, void *addr))
119 {
120 char buf[PRINT_BUF_SIZE];
121 int printed = vsnprintf(buf, PRINT_BUF_SIZE, fmt, args);
122 if (printed > PRINT_BUF_SIZE - 1) {
123 printed = PRINT_BUF_SIZE - 1;
124 }
125 #if 0 // this can be switched on if we want pre-main logs
126 buf[printed] = '\n';
127 write(STDOUT_FILENO, buf, printed);
128 #else
129 PT_LOG(buf);
130 #endif
131 }
132
133
134 // The panic() mock works in conjunction with T_ASSERT_PANIC()
135 // XNU code that panics doesn't expect panic() to return so any function that calls panic() doesn't bother
136 // to return gracefully to its caller with an error.
137 // In a unit-test we still want to call a function that is expected to panic, and then be able to run code after it.
138 // T_ASSERT_PANIC creates a setjmp() point before the call that is expected to panic.
139 // Once the panic callback panic_trap_to_debugger() is called it does a longjmp() to that jump point.
140 // This has a similar effect as C++ exceptions, except that any memory allocations performed by the code
141 // prior to the panic are going to be leaked.
142
143 T_MOCK(void,
144 panic_trap_to_debugger, (const char *panic_format_str, va_list * panic_args,
145 unsigned int reason, void *ctx, uint64_t panic_options_mask, void *panic_data,
146 unsigned long panic_caller, const char *panic_initiator))
147 {
148 char buf[PRINT_BUF_SIZE];
149 vsnprintf(buf, PRINT_BUF_SIZE, panic_format_str, *panic_args);
150 PT_LOG_OR_RAW_FMTSTR("panic! %s", buf);
151 ut_check_expected_panic(buf); // may not return
152 PT_FAIL("Panic was unexpected, exiting");
153 abort();
154 }
155
156 T_MOCK(void,
157 vm_sanitize_send_telemetry, (
158 vm_sanitize_method_t method,
159 vm_sanitize_checker_t checker,
160 vm_sanitize_checker_count_t checker_count,
161 enum vm_sanitize_subsys_error_codes ktriage_code,
162 uint64_t arg1,
163 uint64_t arg2,
164 uint64_t arg3,
165 uint64_t arg4,
166 uint64_t future_ret,
167 uint64_t past_ret))
168 {
169 }
170
171 #if (DEBUG || DEVELOPMENT)
172
173 T_MOCK(vm_size_t,
174 zone_element_info, (
175 void *addr,
176 vm_tag_t * ptag))
177 {
178 return 0;
179 }
180
181 #endif // DEBUG || DEVELOPMENT
182
183 // added for setup_nested_submap()
184 T_MOCK(kern_return_t,
185 csm_setup_nested_address_space, (
186 pmap_t pmap,
187 const vm_address_t region_addr,
188 const vm_size_t region_size))
189 {
190 return KERN_SUCCESS;
191 }
192
193 T_MOCK(btref_t,
194 btref_get, (
195 void *fp,
196 btref_get_flags_t flags))
197 {
198 return 0;
199 }
200
201 #if (DEBUG || DEVELOPMENT)
202 // these are used for testing the mocking framework, xnu has them only in development || debug
203 T_MOCK_DYNAMIC(size_t, kernel_func1, (int a, char b), (a, b), { return 0; });
204 T_MOCK_DYNAMIC(size_t, kernel_func2, (int a, char b), (a, b), { return 0; });
205 T_MOCK_DYNAMIC(size_t, kernel_func3, (int a, char b), (a, b), { return 0; });
206 T_MOCK_DYNAMIC(size_t, kernel_func4, (int a, char b), (a, b), { return 0; });
207 T_MOCK_DYNAMIC(size_t, kernel_func5, (int a, char b), (a, b), { return kernel_func5(a, b); });
208 T_MOCK_DYNAMIC(void, kernel_func6, (int a, char b), (a, b), { kernel_func6(a, b); });
209 T_MOCK_DYNAMIC(size_t, kernel_func7, (int a, char b), (a, b));
210 T_MOCK_DYNAMIC(void, kernel_func8, (int a, char b), (a, b));
211 #endif // DEBUG || DEVELOPMENT
212