1/*
2 * Copyright (c) 2011 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/*
30 * Make sure we don't accidentally include the external definitions of
31 * the routines we're interposing on below.
32 */
33#define _vm_map_user_
34#define _mach_vm_user_
35#include <mach/mach.h>
36#include <mach/mach_traps.h>
37#undef _vm_map_user_
38#include <mach/vm_map_internal.h>
39#undef _mach_vm_user_
40#include <mach/mach_vm_internal.h>
41
42#include "stack_logging_internal.h"
43
44malloc_logger_t *__syscall_logger = NULL;   // This may get set by Libc's malloc stack logging initialization code.
45
46kern_return_t
47mach_vm_allocate(
48	mach_port_name_t target,
49	mach_vm_address_t *address,
50	mach_vm_size_t size,
51	int flags)
52{
53	kern_return_t rv;
54
55	rv = _kernelrpc_mach_vm_allocate_trap(target, address, size, flags);
56
57	if (rv == MACH_SEND_INVALID_DEST)
58		rv = _kernelrpc_mach_vm_allocate(target, address, size, flags);
59
60	if (__syscall_logger) {
61		int userTagFlags = flags & VM_FLAGS_ALIAS_MASK;
62		__syscall_logger(stack_logging_type_vm_allocate | userTagFlags, (uintptr_t)target, (uintptr_t)size, 0, (uintptr_t)*address, 0);
63	}
64
65	return (rv);
66}
67
68kern_return_t
69mach_vm_deallocate(
70	mach_port_name_t target,
71	mach_vm_address_t address,
72	mach_vm_size_t size)
73{
74	kern_return_t rv;
75
76	rv = _kernelrpc_mach_vm_deallocate_trap(target, address, size);
77
78	if (rv == MACH_SEND_INVALID_DEST)
79		rv = _kernelrpc_mach_vm_deallocate(target, address, size);
80
81	if (__syscall_logger) {
82		__syscall_logger(stack_logging_type_vm_deallocate, (uintptr_t)target, (uintptr_t)address, (uintptr_t)size, 0, 0);
83	}
84
85	return (rv);
86}
87
88kern_return_t
89mach_vm_protect(
90	mach_port_name_t task,
91	mach_vm_address_t address,
92	mach_vm_size_t size,
93	boolean_t set_maximum,
94	vm_prot_t new_protection)
95{
96	kern_return_t rv;
97
98	rv = _kernelrpc_mach_vm_protect_trap(task, address, size, set_maximum,
99		new_protection);
100
101	if (rv == MACH_SEND_INVALID_DEST)
102		rv = _kernelrpc_mach_vm_protect(task, address, size,
103			set_maximum, new_protection);
104
105	return (rv);
106}
107
108kern_return_t
109vm_allocate(
110	mach_port_name_t task,
111	vm_address_t *address,
112	vm_size_t size,
113	int flags)
114{
115	kern_return_t rv;
116	mach_vm_address_t mach_addr;
117
118	mach_addr = (mach_vm_address_t)*address;
119	rv = mach_vm_allocate(task, &mach_addr, size, flags);
120#if defined(__LP64__)
121	*address = mach_addr;
122#else
123	*address = (vm_address_t)(mach_addr & ((vm_address_t)-1));
124#endif
125
126	return (rv);
127}
128
129kern_return_t
130vm_deallocate(
131	mach_port_name_t task,
132	vm_address_t address,
133	vm_size_t size)
134{
135	kern_return_t rv;
136
137	rv = mach_vm_deallocate(task, address, size);
138
139	return (rv);
140}
141
142kern_return_t
143vm_protect(
144	mach_port_name_t task,
145	vm_address_t address,
146	vm_size_t size,
147	boolean_t set_maximum,
148	vm_prot_t new_protection)
149{
150	kern_return_t rv;
151
152	rv = mach_vm_protect(task, address, size, set_maximum, new_protection);
153
154	return (rv);
155}
156
157kern_return_t
158mach_vm_map(
159	mach_port_name_t target,
160	mach_vm_address_t *address,
161	mach_vm_size_t size,
162	mach_vm_offset_t mask,
163	int flags,
164	mem_entry_name_port_t object,
165	memory_object_offset_t offset,
166	boolean_t copy,
167	vm_prot_t cur_protection,
168	vm_prot_t max_protection,
169	vm_inherit_t inheritance)
170{
171	kern_return_t rv = MACH_SEND_INVALID_DEST;
172
173	if (object == MEMORY_OBJECT_NULL && max_protection == VM_PROT_ALL &&
174			inheritance == VM_INHERIT_DEFAULT)
175		rv = _kernelrpc_mach_vm_map_trap(target, address, size, mask, flags,
176				cur_protection);
177
178	if (rv == MACH_SEND_INVALID_DEST)
179		rv = _kernelrpc_mach_vm_map(target, address, size, mask, flags, object,
180			offset, copy, cur_protection, max_protection, inheritance);
181
182	if (__syscall_logger) {
183		int eventTypeFlags = stack_logging_type_vm_allocate | stack_logging_type_mapped_file_or_shared_mem;
184		int userTagFlags = flags & VM_FLAGS_ALIAS_MASK;
185		__syscall_logger(eventTypeFlags | userTagFlags, (uintptr_t)target, (uintptr_t)size, 0, (uintptr_t)*address, 0);
186	}
187
188	return (rv);
189}
190
191kern_return_t
192mach_vm_remap(
193	mach_port_name_t target,
194	mach_vm_address_t *address,
195	mach_vm_size_t size,
196	mach_vm_offset_t mask,
197	int flags,
198	mach_port_name_t src_task,
199	mach_vm_address_t src_address,
200	boolean_t copy,
201	vm_prot_t *cur_protection,
202	vm_prot_t *max_protection,
203        vm_inherit_t inheritance)
204{
205	kern_return_t rv;
206
207	rv = _kernelrpc_mach_vm_remap(target, address, size, mask, flags,
208		src_task, src_address, copy, cur_protection, max_protection,
209		inheritance);
210
211	if (__syscall_logger) {
212		int eventTypeFlags = stack_logging_type_vm_allocate | stack_logging_type_mapped_file_or_shared_mem;
213		int userTagFlags = flags & VM_FLAGS_ALIAS_MASK;
214		__syscall_logger(eventTypeFlags | userTagFlags, (uintptr_t)target, (uintptr_t)size, 0, (uintptr_t)*address, 0);
215	}
216
217	return (rv);
218}
219
220kern_return_t
221mach_vm_read(
222	mach_port_name_t target,
223	mach_vm_address_t address,
224	mach_vm_size_t size,
225	vm_offset_t *data,
226	mach_msg_type_number_t *dataCnt)
227{
228	kern_return_t rv;
229
230	rv = _kernelrpc_mach_vm_read(target, address, size, data, dataCnt);
231
232	if (__syscall_logger) {
233		int eventTypeFlags = stack_logging_type_vm_allocate | stack_logging_type_mapped_file_or_shared_mem;
234		// The target argument is the remote task from which data is being read,
235		// so pass mach_task_self() as the destination task receiving the allocation.
236		__syscall_logger(eventTypeFlags, (uintptr_t)mach_task_self(), (uintptr_t)*dataCnt, 0, *data, 0);
237	}
238
239	return (rv);
240}
241
242kern_return_t
243vm_map(
244	mach_port_name_t target,
245	vm_address_t *address,
246	vm_size_t size,
247	vm_offset_t mask,
248	int flags,
249	mem_entry_name_port_t object,
250	vm_offset_t offset,
251	boolean_t copy,
252	vm_prot_t cur_protection,
253	vm_prot_t max_protection,
254	vm_inherit_t inheritance)
255{
256	kern_return_t rv;
257
258	rv = _kernelrpc_vm_map(target, address, size, mask, flags, object,
259		offset, copy, cur_protection, max_protection, inheritance);
260
261	if (__syscall_logger) {
262		int eventTypeFlags = stack_logging_type_vm_allocate | stack_logging_type_mapped_file_or_shared_mem;
263		int userTagFlags = flags & VM_FLAGS_ALIAS_MASK;
264		__syscall_logger(eventTypeFlags | userTagFlags, (uintptr_t)target, (uintptr_t)size, 0, (uintptr_t)*address, 0);
265	}
266
267	return (rv);
268}
269
270kern_return_t
271vm_remap(
272	mach_port_name_t target,
273	vm_address_t *address,
274	vm_size_t size,
275	vm_offset_t mask,
276	int flags,
277	mach_port_name_t src_task,
278	vm_address_t src_address,
279	boolean_t copy,
280	vm_prot_t *cur_protection,
281	vm_prot_t *max_protection,
282        vm_inherit_t inheritance)
283{
284	kern_return_t rv;
285
286	rv = _kernelrpc_vm_remap(target, address, size, mask, flags,
287		src_task, src_address, copy, cur_protection, max_protection,
288		inheritance);
289
290	if (__syscall_logger) {
291		int eventTypeFlags = stack_logging_type_vm_allocate | stack_logging_type_mapped_file_or_shared_mem;
292		int userTagFlags = flags & VM_FLAGS_ALIAS_MASK;
293		__syscall_logger(eventTypeFlags | userTagFlags, (uintptr_t)target, (uintptr_t)size, 0, (uintptr_t)*address, 0);
294	}
295
296	return (rv);
297}
298
299kern_return_t
300vm_read(
301	mach_port_name_t target,
302	vm_address_t address,
303	vm_size_t size,
304	vm_offset_t *data,
305	mach_msg_type_number_t *dataCnt)
306{
307	kern_return_t rv;
308
309	rv = _kernelrpc_vm_read(target, address, size, data, dataCnt);
310
311	if (__syscall_logger) {
312		int eventTypeFlags = stack_logging_type_vm_allocate | stack_logging_type_mapped_file_or_shared_mem;
313		// The target argument is the remote task from which data is being read,
314		// so pass mach_task_self() as the destination task receiving the allocation.
315		__syscall_logger(eventTypeFlags, (uintptr_t)mach_task_self(), (uintptr_t)*dataCnt, 0, *data, 0);
316	}
317
318	return (rv);
319}
320