]>
Commit | Line | Data |
---|---|---|
316670eb A |
1 | /* |
2 | * Copyright (c) 2011 Apple Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ | |
0a7de745 | 5 | * |
316670eb A |
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. | |
0a7de745 | 14 | * |
316670eb A |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
0a7de745 | 17 | * |
316670eb A |
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. | |
0a7de745 | 25 | * |
316670eb A |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
27 | */ | |
28 | ||
29 | #include <mach/mach_types.h> | |
30 | #include <mach/mach_traps.h> | |
31 | #include <mach/mach_vm_server.h> | |
32 | #include <mach/mach_port_server.h> | |
39037602 A |
33 | #include <mach/mach_host_server.h> |
34 | #include <mach/mach_voucher_server.h> | |
316670eb A |
35 | #include <mach/vm_map.h> |
36 | #include <kern/task.h> | |
37 | #include <kern/ipc_tt.h> | |
39037602 | 38 | #include <kern/kalloc.h> |
316670eb A |
39 | #include <vm/vm_protos.h> |
40 | ||
f427ee49 A |
41 | kern_return_t |
42 | mach_port_get_attributes( | |
43 | ipc_space_t space, | |
44 | mach_port_name_t name, | |
45 | int flavor, | |
46 | mach_port_info_t info, | |
47 | mach_msg_type_number_t *count); | |
48 | ||
316670eb A |
49 | int |
50 | _kernelrpc_mach_vm_allocate_trap(struct _kernelrpc_mach_vm_allocate_trap_args *args) | |
51 | { | |
52 | mach_vm_offset_t addr; | |
53 | task_t task = port_name_to_task(args->target); | |
54 | int rv = MACH_SEND_INVALID_DEST; | |
55 | ||
0a7de745 | 56 | if (task != current_task()) { |
316670eb | 57 | goto done; |
0a7de745 | 58 | } |
316670eb | 59 | |
0a7de745 | 60 | if (copyin(args->addr, (char *)&addr, sizeof(addr))) { |
316670eb | 61 | goto done; |
0a7de745 | 62 | } |
316670eb | 63 | |
5ba3f43e | 64 | rv = mach_vm_allocate_external(task->map, &addr, args->size, args->flags); |
0a7de745 A |
65 | if (rv == KERN_SUCCESS) { |
66 | rv = copyout(&addr, args->addr, sizeof(addr)); | |
67 | } | |
68 | ||
316670eb | 69 | done: |
0a7de745 | 70 | if (task) { |
316670eb | 71 | task_deallocate(task); |
0a7de745 A |
72 | } |
73 | return rv; | |
316670eb A |
74 | } |
75 | ||
76 | int | |
77 | _kernelrpc_mach_vm_deallocate_trap(struct _kernelrpc_mach_vm_deallocate_args *args) | |
78 | { | |
79 | task_t task = port_name_to_task(args->target); | |
80 | int rv = MACH_SEND_INVALID_DEST; | |
81 | ||
0a7de745 | 82 | if (task != current_task()) { |
316670eb | 83 | goto done; |
0a7de745 | 84 | } |
316670eb A |
85 | |
86 | rv = mach_vm_deallocate(task->map, args->address, args->size); | |
0a7de745 | 87 | |
316670eb | 88 | done: |
0a7de745 | 89 | if (task) { |
316670eb | 90 | task_deallocate(task); |
0a7de745 A |
91 | } |
92 | return rv; | |
316670eb A |
93 | } |
94 | ||
95 | int | |
96 | _kernelrpc_mach_vm_protect_trap(struct _kernelrpc_mach_vm_protect_args *args) | |
97 | { | |
98 | task_t task = port_name_to_task(args->target); | |
99 | int rv = MACH_SEND_INVALID_DEST; | |
100 | ||
0a7de745 | 101 | if (task != current_task()) { |
316670eb | 102 | goto done; |
0a7de745 | 103 | } |
316670eb A |
104 | |
105 | rv = mach_vm_protect(task->map, args->address, args->size, | |
106 | args->set_maximum, args->new_protection); | |
0a7de745 | 107 | |
316670eb | 108 | done: |
0a7de745 | 109 | if (task) { |
316670eb | 110 | task_deallocate(task); |
0a7de745 A |
111 | } |
112 | return rv; | |
316670eb A |
113 | } |
114 | ||
39236c6e A |
115 | int |
116 | _kernelrpc_mach_vm_map_trap(struct _kernelrpc_mach_vm_map_trap_args *args) | |
117 | { | |
118 | mach_vm_offset_t addr; | |
119 | task_t task = port_name_to_task(args->target); | |
120 | int rv = MACH_SEND_INVALID_DEST; | |
121 | ||
0a7de745 | 122 | if (task != current_task()) { |
39236c6e | 123 | goto done; |
0a7de745 | 124 | } |
39236c6e | 125 | |
0a7de745 | 126 | if (copyin(args->addr, (char *)&addr, sizeof(addr))) { |
39236c6e | 127 | goto done; |
0a7de745 | 128 | } |
39236c6e | 129 | |
5ba3f43e | 130 | rv = mach_vm_map_external(task->map, &addr, args->size, args->mask, args->flags, |
0a7de745 A |
131 | IPC_PORT_NULL, 0, FALSE, args->cur_protection, VM_PROT_ALL, |
132 | VM_INHERIT_DEFAULT); | |
133 | if (rv == KERN_SUCCESS) { | |
134 | rv = copyout(&addr, args->addr, sizeof(addr)); | |
135 | } | |
39236c6e A |
136 | |
137 | done: | |
0a7de745 | 138 | if (task) { |
39236c6e | 139 | task_deallocate(task); |
0a7de745 A |
140 | } |
141 | return rv; | |
39236c6e A |
142 | } |
143 | ||
39037602 A |
144 | int |
145 | _kernelrpc_mach_vm_purgable_control_trap( | |
146 | struct _kernelrpc_mach_vm_purgable_control_trap_args *args) | |
147 | { | |
148 | int state; | |
149 | task_t task = port_name_to_task(args->target); | |
150 | int rv = MACH_SEND_INVALID_DEST; | |
151 | ||
0a7de745 | 152 | if (task != current_task()) { |
39037602 | 153 | goto done; |
0a7de745 | 154 | } |
39037602 | 155 | |
0a7de745 | 156 | if (copyin(args->state, (char *)&state, sizeof(state))) { |
39037602 | 157 | goto done; |
0a7de745 | 158 | } |
39037602 A |
159 | |
160 | rv = mach_vm_purgable_control(task->map, | |
0a7de745 A |
161 | args->address, |
162 | args->control, | |
163 | &state); | |
164 | if (rv == KERN_SUCCESS) { | |
165 | rv = copyout(&state, args->state, sizeof(state)); | |
166 | } | |
167 | ||
39037602 | 168 | done: |
0a7de745 | 169 | if (task) { |
39037602 | 170 | task_deallocate(task); |
0a7de745 A |
171 | } |
172 | return rv; | |
39037602 A |
173 | } |
174 | ||
316670eb A |
175 | int |
176 | _kernelrpc_mach_port_allocate_trap(struct _kernelrpc_mach_port_allocate_args *args) | |
177 | { | |
178 | task_t task = port_name_to_task(args->target); | |
179 | mach_port_name_t name; | |
180 | int rv = MACH_SEND_INVALID_DEST; | |
181 | ||
0a7de745 | 182 | if (task != current_task()) { |
316670eb | 183 | goto done; |
0a7de745 | 184 | } |
316670eb A |
185 | |
186 | rv = mach_port_allocate(task->itk_space, args->right, &name); | |
0a7de745 A |
187 | if (rv == KERN_SUCCESS) { |
188 | rv = copyout(&name, args->name, sizeof(name)); | |
189 | } | |
190 | ||
316670eb | 191 | |
316670eb | 192 | done: |
0a7de745 | 193 | if (task) { |
316670eb | 194 | task_deallocate(task); |
0a7de745 A |
195 | } |
196 | return rv; | |
316670eb A |
197 | } |
198 | ||
316670eb A |
199 | int |
200 | _kernelrpc_mach_port_deallocate_trap(struct _kernelrpc_mach_port_deallocate_args *args) | |
201 | { | |
202 | task_t task = port_name_to_task(args->target); | |
203 | int rv = MACH_SEND_INVALID_DEST; | |
204 | ||
0a7de745 | 205 | if (task != current_task()) { |
316670eb | 206 | goto done; |
0a7de745 | 207 | } |
316670eb A |
208 | |
209 | rv = mach_port_deallocate(task->itk_space, args->name); | |
0a7de745 | 210 | |
316670eb | 211 | done: |
0a7de745 | 212 | if (task) { |
316670eb | 213 | task_deallocate(task); |
0a7de745 A |
214 | } |
215 | return rv; | |
316670eb A |
216 | } |
217 | ||
218 | int | |
219 | _kernelrpc_mach_port_mod_refs_trap(struct _kernelrpc_mach_port_mod_refs_args *args) | |
220 | { | |
221 | task_t task = port_name_to_task(args->target); | |
222 | int rv = MACH_SEND_INVALID_DEST; | |
223 | ||
0a7de745 | 224 | if (task != current_task()) { |
316670eb | 225 | goto done; |
0a7de745 | 226 | } |
316670eb A |
227 | |
228 | rv = mach_port_mod_refs(task->itk_space, args->name, args->right, args->delta); | |
0a7de745 | 229 | |
316670eb | 230 | done: |
0a7de745 | 231 | if (task) { |
316670eb | 232 | task_deallocate(task); |
0a7de745 A |
233 | } |
234 | return rv; | |
316670eb A |
235 | } |
236 | ||
237 | ||
238 | int | |
239 | _kernelrpc_mach_port_move_member_trap(struct _kernelrpc_mach_port_move_member_args *args) | |
240 | { | |
241 | task_t task = port_name_to_task(args->target); | |
242 | int rv = MACH_SEND_INVALID_DEST; | |
243 | ||
0a7de745 | 244 | if (task != current_task()) { |
316670eb | 245 | goto done; |
0a7de745 | 246 | } |
316670eb A |
247 | |
248 | rv = mach_port_move_member(task->itk_space, args->member, args->after); | |
0a7de745 | 249 | |
316670eb | 250 | done: |
0a7de745 | 251 | if (task) { |
316670eb | 252 | task_deallocate(task); |
0a7de745 A |
253 | } |
254 | return rv; | |
316670eb A |
255 | } |
256 | ||
257 | int | |
258 | _kernelrpc_mach_port_insert_right_trap(struct _kernelrpc_mach_port_insert_right_args *args) | |
259 | { | |
260 | task_t task = port_name_to_task(args->target); | |
261 | ipc_port_t port; | |
262 | mach_msg_type_name_t disp; | |
263 | int rv = MACH_SEND_INVALID_DEST; | |
264 | ||
0a7de745 | 265 | if (task != current_task()) { |
316670eb | 266 | goto done; |
0a7de745 | 267 | } |
316670eb | 268 | |
cb323159 A |
269 | if (args->name == args->poly) { |
270 | switch (args->polyPoly) { | |
271 | case MACH_MSG_TYPE_MAKE_SEND: | |
272 | case MACH_MSG_TYPE_COPY_SEND: | |
273 | /* fastpath MAKE_SEND / COPY_SEND which is the most common case */ | |
274 | rv = ipc_object_insert_send_right(task->itk_space, args->poly, | |
275 | args->polyPoly); | |
276 | goto done; | |
277 | ||
278 | default: | |
279 | break; | |
280 | } | |
281 | } | |
282 | ||
316670eb | 283 | rv = ipc_object_copyin(task->itk_space, args->poly, args->polyPoly, |
cb323159 | 284 | (ipc_object_t *)&port, 0, NULL, IPC_KMSG_FLAGS_ALLOW_IMMOVABLE_SEND); |
0a7de745 | 285 | if (rv != KERN_SUCCESS) { |
316670eb | 286 | goto done; |
0a7de745 | 287 | } |
316670eb A |
288 | disp = ipc_object_copyin_type(args->polyPoly); |
289 | ||
290 | rv = mach_port_insert_right(task->itk_space, args->name, port, disp); | |
cb323159 A |
291 | if (rv != KERN_SUCCESS && IP_VALID(port)) { |
292 | ipc_object_destroy(ip_to_object(port), disp); | |
d190cdc3 | 293 | } |
0a7de745 | 294 | |
316670eb | 295 | done: |
0a7de745 | 296 | if (task) { |
316670eb | 297 | task_deallocate(task); |
0a7de745 A |
298 | } |
299 | return rv; | |
316670eb A |
300 | } |
301 | ||
d9a64523 A |
302 | int |
303 | _kernelrpc_mach_port_get_attributes_trap(struct _kernelrpc_mach_port_get_attributes_args *args) | |
304 | { | |
f427ee49 | 305 | task_inspect_t task = port_name_to_task_read_no_eval(args->target); |
d9a64523 A |
306 | int rv = MACH_SEND_INVALID_DEST; |
307 | mach_msg_type_number_t count; | |
308 | ||
0a7de745 | 309 | if (task != current_task()) { |
d9a64523 | 310 | goto done; |
0a7de745 | 311 | } |
d9a64523 A |
312 | |
313 | // MIG does not define the type or size of the mach_port_info_t out array | |
314 | // anywhere, so derive them from the field in the generated reply struct | |
f427ee49 | 315 | #define MACH_PORT_INFO_OUT (((__Reply__mach_port_get_attributes_from_user_t*)NULL)->port_info_out) |
d9a64523 A |
316 | #define MACH_PORT_INFO_STACK_LIMIT 80 // current size is 68 == 17 * sizeof(integer_t) |
317 | _Static_assert(sizeof(MACH_PORT_INFO_OUT) < MACH_PORT_INFO_STACK_LIMIT, | |
0a7de745 A |
318 | "mach_port_info_t has grown significantly, reevaluate stack usage"); |
319 | const mach_msg_type_number_t max_count = (sizeof(MACH_PORT_INFO_OUT) / sizeof(MACH_PORT_INFO_OUT[0])); | |
d9a64523 A |
320 | typeof(MACH_PORT_INFO_OUT[0]) info[max_count]; |
321 | ||
b226f5e5 A |
322 | /* |
323 | * zero out our stack buffer because not all flavors of | |
324 | * port_get_attributes initialize the whole struct | |
325 | */ | |
326 | bzero(info, sizeof(MACH_PORT_INFO_OUT)); | |
327 | ||
d9a64523 A |
328 | if (copyin(CAST_USER_ADDR_T(args->count), &count, sizeof(count))) { |
329 | rv = MACH_SEND_INVALID_DATA; | |
330 | goto done; | |
331 | } | |
0a7de745 | 332 | if (count > max_count) { |
d9a64523 | 333 | count = max_count; |
0a7de745 | 334 | } |
d9a64523 A |
335 | |
336 | rv = mach_port_get_attributes(task->itk_space, args->name, args->flavor, info, &count); | |
0a7de745 | 337 | if (rv == KERN_SUCCESS) { |
d9a64523 | 338 | rv = copyout(&count, CAST_USER_ADDR_T(args->count), sizeof(count)); |
0a7de745 A |
339 | } |
340 | if (rv == KERN_SUCCESS && count > 0) { | |
d9a64523 | 341 | rv = copyout(info, CAST_USER_ADDR_T(args->info), count * sizeof(info[0])); |
0a7de745 | 342 | } |
d9a64523 A |
343 | |
344 | done: | |
0a7de745 | 345 | if (task) { |
d9a64523 | 346 | task_deallocate(task); |
0a7de745 A |
347 | } |
348 | return rv; | |
d9a64523 A |
349 | } |
350 | ||
316670eb A |
351 | int |
352 | _kernelrpc_mach_port_insert_member_trap(struct _kernelrpc_mach_port_insert_member_args *args) | |
353 | { | |
354 | task_t task = port_name_to_task(args->target); | |
355 | int rv = MACH_SEND_INVALID_DEST; | |
356 | ||
0a7de745 | 357 | if (task != current_task()) { |
316670eb | 358 | goto done; |
0a7de745 | 359 | } |
316670eb A |
360 | |
361 | rv = mach_port_insert_member(task->itk_space, args->name, args->pset); | |
0a7de745 | 362 | |
316670eb | 363 | done: |
0a7de745 | 364 | if (task) { |
316670eb | 365 | task_deallocate(task); |
0a7de745 A |
366 | } |
367 | return rv; | |
316670eb A |
368 | } |
369 | ||
370 | ||
371 | int | |
372 | _kernelrpc_mach_port_extract_member_trap(struct _kernelrpc_mach_port_extract_member_args *args) | |
373 | { | |
374 | task_t task = port_name_to_task(args->target); | |
375 | int rv = MACH_SEND_INVALID_DEST; | |
376 | ||
0a7de745 | 377 | if (task != current_task()) { |
316670eb | 378 | goto done; |
0a7de745 | 379 | } |
316670eb A |
380 | |
381 | rv = mach_port_extract_member(task->itk_space, args->name, args->pset); | |
0a7de745 | 382 | |
316670eb | 383 | done: |
0a7de745 | 384 | if (task) { |
316670eb | 385 | task_deallocate(task); |
0a7de745 A |
386 | } |
387 | return rv; | |
316670eb | 388 | } |
39236c6e A |
389 | |
390 | int | |
391 | _kernelrpc_mach_port_construct_trap(struct _kernelrpc_mach_port_construct_args *args) | |
392 | { | |
393 | task_t task = port_name_to_task(args->target); | |
394 | mach_port_name_t name; | |
395 | int rv = MACH_SEND_INVALID_DEST; | |
396 | mach_port_options_t options; | |
397 | ||
0a7de745 | 398 | if (copyin(args->options, (char *)&options, sizeof(options))) { |
39236c6e A |
399 | rv = MACH_SEND_INVALID_DATA; |
400 | goto done; | |
401 | } | |
402 | ||
0a7de745 | 403 | if (task != current_task()) { |
39236c6e | 404 | goto done; |
0a7de745 | 405 | } |
39236c6e A |
406 | |
407 | rv = mach_port_construct(task->itk_space, &options, args->context, &name); | |
0a7de745 A |
408 | if (rv == KERN_SUCCESS) { |
409 | rv = copyout(&name, args->name, sizeof(name)); | |
410 | } | |
39236c6e A |
411 | |
412 | done: | |
0a7de745 | 413 | if (task) { |
39236c6e | 414 | task_deallocate(task); |
0a7de745 A |
415 | } |
416 | return rv; | |
39236c6e A |
417 | } |
418 | ||
419 | int | |
420 | _kernelrpc_mach_port_destruct_trap(struct _kernelrpc_mach_port_destruct_args *args) | |
421 | { | |
422 | task_t task = port_name_to_task(args->target); | |
423 | int rv = MACH_SEND_INVALID_DEST; | |
424 | ||
0a7de745 | 425 | if (task != current_task()) { |
39236c6e | 426 | goto done; |
0a7de745 | 427 | } |
39236c6e A |
428 | |
429 | rv = mach_port_destruct(task->itk_space, args->name, args->srdelta, args->guard); | |
0a7de745 | 430 | |
39236c6e | 431 | done: |
0a7de745 | 432 | if (task) { |
39236c6e | 433 | task_deallocate(task); |
0a7de745 A |
434 | } |
435 | return rv; | |
39236c6e A |
436 | } |
437 | ||
438 | int | |
439 | _kernelrpc_mach_port_guard_trap(struct _kernelrpc_mach_port_guard_args *args) | |
440 | { | |
441 | task_t task = port_name_to_task(args->target); | |
442 | int rv = MACH_SEND_INVALID_DEST; | |
443 | ||
0a7de745 | 444 | if (task != current_task()) { |
39236c6e | 445 | goto done; |
0a7de745 | 446 | } |
39236c6e A |
447 | |
448 | rv = mach_port_guard(task->itk_space, args->name, args->guard, args->strict); | |
0a7de745 | 449 | |
39236c6e | 450 | done: |
0a7de745 | 451 | if (task) { |
39236c6e | 452 | task_deallocate(task); |
0a7de745 A |
453 | } |
454 | return rv; | |
39236c6e A |
455 | } |
456 | ||
457 | int | |
458 | _kernelrpc_mach_port_unguard_trap(struct _kernelrpc_mach_port_unguard_args *args) | |
459 | { | |
460 | task_t task = port_name_to_task(args->target); | |
461 | int rv = MACH_SEND_INVALID_DEST; | |
462 | ||
0a7de745 | 463 | if (task != current_task()) { |
39236c6e | 464 | goto done; |
0a7de745 | 465 | } |
39236c6e A |
466 | |
467 | rv = mach_port_unguard(task->itk_space, args->name, args->guard); | |
0a7de745 | 468 | |
39236c6e | 469 | done: |
0a7de745 | 470 | if (task) { |
39236c6e | 471 | task_deallocate(task); |
0a7de745 A |
472 | } |
473 | return rv; | |
39236c6e A |
474 | } |
475 | ||
cb323159 A |
476 | int |
477 | _kernelrpc_mach_port_type_trap(struct _kernelrpc_mach_port_type_args *args) | |
478 | { | |
479 | task_t task = port_name_to_task(args->target); | |
480 | int rv = MACH_SEND_INVALID_DEST; | |
481 | mach_port_type_t type; | |
482 | ||
483 | if (task != current_task()) { | |
484 | goto done; | |
485 | } | |
486 | ||
487 | rv = mach_port_type(task->itk_space, args->name, &type); | |
488 | if (rv == KERN_SUCCESS) { | |
489 | rv = copyout(&type, args->ptype, sizeof(type)); | |
490 | } | |
491 | ||
492 | done: | |
493 | if (task) { | |
494 | task_deallocate(task); | |
495 | } | |
496 | return rv; | |
497 | } | |
498 | ||
499 | int | |
500 | _kernelrpc_mach_port_request_notification_trap( | |
501 | struct _kernelrpc_mach_port_request_notification_args *args) | |
502 | { | |
503 | task_t task = port_name_to_task(args->target); | |
504 | int rv = MACH_SEND_INVALID_DEST; | |
505 | ipc_port_t notify, previous; | |
506 | mach_msg_type_name_t disp; | |
507 | mach_port_name_t previous_name = MACH_PORT_NULL; | |
508 | ||
509 | if (task != current_task()) { | |
510 | goto done; | |
511 | } | |
512 | ||
513 | disp = ipc_object_copyin_type(args->notifyPoly); | |
514 | if (disp != MACH_MSG_TYPE_PORT_SEND_ONCE) { | |
515 | goto done; | |
516 | } | |
517 | ||
518 | if (MACH_PORT_VALID(args->notify)) { | |
519 | rv = ipc_object_copyin(task->itk_space, args->notify, args->notifyPoly, | |
520 | (ipc_object_t *)¬ify, 0, NULL, 0); | |
521 | } else { | |
522 | notify = CAST_MACH_NAME_TO_PORT(args->notify); | |
523 | } | |
524 | if (rv != KERN_SUCCESS) { | |
525 | goto done; | |
526 | } | |
527 | ||
528 | rv = mach_port_request_notification(task->itk_space, args->name, | |
529 | args->msgid, args->sync, notify, &previous); | |
530 | if (rv != KERN_SUCCESS) { | |
531 | ipc_object_destroy(ip_to_object(notify), disp); | |
532 | goto done; | |
533 | } | |
534 | ||
535 | if (IP_VALID(previous)) { | |
536 | // Remove once <rdar://problem/45522961> is fixed. | |
537 | // We need to make ith_knote NULL as ipc_object_copyout() uses | |
538 | // thread-argument-passing and its value should not be garbage | |
539 | current_thread()->ith_knote = ITH_KNOTE_NULL; | |
540 | rv = ipc_object_copyout(task->itk_space, ip_to_object(previous), | |
541 | MACH_MSG_TYPE_PORT_SEND_ONCE, NULL, NULL, &previous_name); | |
542 | if (rv != KERN_SUCCESS) { | |
543 | ipc_object_destroy(ip_to_object(previous), | |
544 | MACH_MSG_TYPE_PORT_SEND_ONCE); | |
545 | goto done; | |
546 | } | |
547 | } | |
548 | ||
549 | rv = copyout(&previous_name, args->previous, sizeof(previous_name)); | |
550 | ||
551 | done: | |
552 | if (task) { | |
553 | task_deallocate(task); | |
554 | } | |
555 | return rv; | |
556 | } | |
557 | ||
39037602 A |
558 | kern_return_t |
559 | host_create_mach_voucher_trap(struct host_create_mach_voucher_args *args) | |
560 | { | |
561 | host_t host = port_name_to_host(args->host); | |
562 | ipc_voucher_t new_voucher = IV_NULL; | |
563 | ipc_port_t voucher_port = IPC_PORT_NULL; | |
564 | mach_port_name_t voucher_name = 0; | |
f427ee49 | 565 | kern_return_t kr = KERN_SUCCESS; |
39037602 | 566 | |
0a7de745 | 567 | if (host == HOST_NULL) { |
39037602 | 568 | return MACH_SEND_INVALID_DEST; |
0a7de745 | 569 | } |
0a7de745 | 570 | if (args->recipes_size < 0) { |
39037602 | 571 | return KERN_INVALID_ARGUMENT; |
f427ee49 A |
572 | } |
573 | if (args->recipes_size > MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE) { | |
39037602 | 574 | return MIG_ARRAY_TOO_LARGE; |
0a7de745 | 575 | } |
39037602 | 576 | |
f427ee49 A |
577 | /* keep small recipes on the stack for speed */ |
578 | uint8_t buf[MACH_VOUCHER_TRAP_STACK_LIMIT]; | |
579 | uint8_t *krecipes = buf; | |
39037602 | 580 | |
f427ee49 A |
581 | if (args->recipes_size > MACH_VOUCHER_TRAP_STACK_LIMIT) { |
582 | krecipes = kheap_alloc(KHEAP_TEMP, args->recipes_size, Z_WAITOK); | |
583 | if (krecipes == NULL) { | |
584 | return KERN_RESOURCE_SHORTAGE; | |
39037602 | 585 | } |
39037602 A |
586 | } |
587 | ||
f427ee49 A |
588 | if (copyin(CAST_USER_ADDR_T(args->recipes), (void *)krecipes, args->recipes_size)) { |
589 | kr = KERN_MEMORY_ERROR; | |
590 | goto done; | |
591 | } | |
39037602 | 592 | |
f427ee49 A |
593 | kr = host_create_mach_voucher(host, krecipes, args->recipes_size, &new_voucher); |
594 | if (kr != KERN_SUCCESS) { | |
595 | goto done; | |
39037602 A |
596 | } |
597 | ||
f427ee49 A |
598 | voucher_port = convert_voucher_to_port(new_voucher); |
599 | voucher_name = ipc_port_copyout_send(voucher_port, current_space()); | |
600 | ||
601 | kr = copyout(&voucher_name, args->voucher, sizeof(voucher_name)); | |
602 | ||
39037602 | 603 | done: |
f427ee49 A |
604 | if (args->recipes_size > MACH_VOUCHER_TRAP_STACK_LIMIT) { |
605 | kheap_free(KHEAP_TEMP, krecipes, args->recipes_size); | |
606 | } | |
607 | ||
39037602 A |
608 | return kr; |
609 | } | |
610 | ||
611 | kern_return_t | |
612 | mach_voucher_extract_attr_recipe_trap(struct mach_voucher_extract_attr_recipe_args *args) | |
613 | { | |
614 | ipc_voucher_t voucher = IV_NULL; | |
615 | kern_return_t kr = KERN_SUCCESS; | |
616 | mach_msg_type_number_t sz = 0; | |
617 | ||
0a7de745 | 618 | if (copyin(args->recipe_size, (void *)&sz, sizeof(sz))) { |
39037602 | 619 | return KERN_MEMORY_ERROR; |
0a7de745 | 620 | } |
39037602 | 621 | |
0a7de745 | 622 | if (sz > MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE) { |
39037602 | 623 | return MIG_ARRAY_TOO_LARGE; |
0a7de745 | 624 | } |
39037602 A |
625 | |
626 | voucher = convert_port_name_to_voucher(args->voucher_name); | |
0a7de745 | 627 | if (voucher == IV_NULL) { |
39037602 | 628 | return MACH_SEND_INVALID_DEST; |
0a7de745 | 629 | } |
39037602 | 630 | |
f427ee49 A |
631 | /* keep small recipes on the stack for speed */ |
632 | uint8_t buf[MACH_VOUCHER_TRAP_STACK_LIMIT]; | |
633 | uint8_t *krecipe = buf; | |
eee35659 | 634 | mach_msg_type_number_t max_sz = sz; |
39037602 | 635 | |
f427ee49 A |
636 | if (max_sz > MACH_VOUCHER_TRAP_STACK_LIMIT) { |
637 | krecipe = kheap_alloc(KHEAP_TEMP, max_sz, Z_WAITOK); | |
39037602 | 638 | if (!krecipe) { |
f427ee49 | 639 | return KERN_RESOURCE_SHORTAGE; |
39037602 | 640 | } |
f427ee49 | 641 | } |
39037602 | 642 | |
f427ee49 A |
643 | if (copyin(CAST_USER_ADDR_T(args->recipe), (void *)krecipe, max_sz)) { |
644 | kr = KERN_MEMORY_ERROR; | |
645 | goto done; | |
646 | } | |
39037602 | 647 | |
f427ee49 A |
648 | kr = mach_voucher_extract_attr_recipe(voucher, args->key, |
649 | (mach_voucher_attr_raw_recipe_t)krecipe, &sz); | |
650 | assert(sz <= max_sz); | |
39037602 | 651 | |
f427ee49 A |
652 | if (kr == KERN_SUCCESS && sz > 0) { |
653 | kr = copyout(krecipe, CAST_USER_ADDR_T(args->recipe), sz); | |
39037602 | 654 | } |
0a7de745 | 655 | if (kr == KERN_SUCCESS) { |
d9a64523 | 656 | kr = copyout(&sz, args->recipe_size, sizeof(sz)); |
0a7de745 | 657 | } |
39037602 | 658 | |
f427ee49 | 659 | |
39037602 | 660 | done: |
f427ee49 A |
661 | if (max_sz > MACH_VOUCHER_TRAP_STACK_LIMIT) { |
662 | kheap_free(KHEAP_TEMP, krecipe, max_sz); | |
663 | } | |
664 | ||
39037602 A |
665 | ipc_voucher_release(voucher); |
666 | return kr; | |
667 | } |