1*4d495c6eSApple OSS Distributions /*
2*4d495c6eSApple OSS Distributions * Copyright (c) 2024 Apple Inc. All rights reserved.
3*4d495c6eSApple OSS Distributions *
4*4d495c6eSApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*4d495c6eSApple OSS Distributions *
6*4d495c6eSApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7*4d495c6eSApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8*4d495c6eSApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9*4d495c6eSApple OSS Distributions * compliance with the License. The rights granted to you under the License
10*4d495c6eSApple OSS Distributions * may not be used to create, or enable the creation or redistribution of,
11*4d495c6eSApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to
12*4d495c6eSApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any
13*4d495c6eSApple OSS Distributions * terms of an Apple operating system software license agreement.
14*4d495c6eSApple OSS Distributions *
15*4d495c6eSApple OSS Distributions * Please obtain a copy of the License at
16*4d495c6eSApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*4d495c6eSApple OSS Distributions *
18*4d495c6eSApple OSS Distributions * The Original Code and all software distributed under the License are
19*4d495c6eSApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*4d495c6eSApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*4d495c6eSApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*4d495c6eSApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*4d495c6eSApple OSS Distributions * Please see the License for the specific language governing rights and
24*4d495c6eSApple OSS Distributions * limitations under the License.
25*4d495c6eSApple OSS Distributions *
26*4d495c6eSApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*4d495c6eSApple OSS Distributions */
28*4d495c6eSApple OSS Distributions
29*4d495c6eSApple OSS Distributions /*
30*4d495c6eSApple OSS Distributions * exc_guard_helper_test.c
31*4d495c6eSApple OSS Distributions *
32*4d495c6eSApple OSS Distributions * Test the testing helper functions in exc_guard_helper.h.
33*4d495c6eSApple OSS Distributions */
34*4d495c6eSApple OSS Distributions
35*4d495c6eSApple OSS Distributions #include "exc_guard_helper.h"
36*4d495c6eSApple OSS Distributions
37*4d495c6eSApple OSS Distributions #include <darwintest.h>
38*4d495c6eSApple OSS Distributions #include <sys/types.h>
39*4d495c6eSApple OSS Distributions #include <sys/sysctl.h>
40*4d495c6eSApple OSS Distributions #include <mach/mach.h>
41*4d495c6eSApple OSS Distributions #include <mach/mach_vm.h>
42*4d495c6eSApple OSS Distributions #include <mach/task_info.h>
43*4d495c6eSApple OSS Distributions #include "test_utils.h"
44*4d495c6eSApple OSS Distributions
45*4d495c6eSApple OSS Distributions T_GLOBAL_META(
46*4d495c6eSApple OSS Distributions T_META_NAMESPACE("xnu"),
47*4d495c6eSApple OSS Distributions T_META_RADAR_COMPONENT_NAME("xnu"),
48*4d495c6eSApple OSS Distributions T_META_RADAR_COMPONENT_VERSION("vm"),
49*4d495c6eSApple OSS Distributions T_META_RUN_CONCURRENTLY(true),
50*4d495c6eSApple OSS Distributions T_META_ALL_VALID_ARCHS(true)
51*4d495c6eSApple OSS Distributions );
52*4d495c6eSApple OSS Distributions
53*4d495c6eSApple OSS Distributions /* Convenience macro for compile-time array size */
54*4d495c6eSApple OSS Distributions #define countof(array) \
55*4d495c6eSApple OSS Distributions _Pragma("clang diagnostic push") \
56*4d495c6eSApple OSS Distributions _Pragma("clang diagnostic error \"-Wsizeof-pointer-div\"") \
57*4d495c6eSApple OSS Distributions (sizeof(array)/sizeof((array)[0])) \
58*4d495c6eSApple OSS Distributions _Pragma("clang diagnostic pop")
59*4d495c6eSApple OSS Distributions
60*4d495c6eSApple OSS Distributions /*
61*4d495c6eSApple OSS Distributions * Return true if [query_start, query_start + query_size) is unallocated memory.
62*4d495c6eSApple OSS Distributions */
63*4d495c6eSApple OSS Distributions static bool
is_hole(mach_vm_address_t query_start,mach_vm_size_t query_size)64*4d495c6eSApple OSS Distributions is_hole(mach_vm_address_t query_start, mach_vm_size_t query_size)
65*4d495c6eSApple OSS Distributions {
66*4d495c6eSApple OSS Distributions mach_vm_address_t entry_start = query_start;
67*4d495c6eSApple OSS Distributions mach_vm_size_t entry_size;
68*4d495c6eSApple OSS Distributions vm_region_submap_info_data_64_t info;
69*4d495c6eSApple OSS Distributions uint32_t depth = 0;
70*4d495c6eSApple OSS Distributions mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64;
71*4d495c6eSApple OSS Distributions kern_return_t kr = mach_vm_region_recurse(mach_task_self(),
72*4d495c6eSApple OSS Distributions &entry_start, &entry_size, &depth,
73*4d495c6eSApple OSS Distributions (vm_region_recurse_info_t)&info, &count);
74*4d495c6eSApple OSS Distributions
75*4d495c6eSApple OSS Distributions if (kr == KERN_INVALID_ADDRESS) {
76*4d495c6eSApple OSS Distributions /*
77*4d495c6eSApple OSS Distributions * query_start is unmapped, and so is everything after it,
78*4d495c6eSApple OSS Distributions * therefore the query range is a hole
79*4d495c6eSApple OSS Distributions */
80*4d495c6eSApple OSS Distributions return true;
81*4d495c6eSApple OSS Distributions }
82*4d495c6eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_region");
83*4d495c6eSApple OSS Distributions
84*4d495c6eSApple OSS Distributions /* this code does not handle submaps */
85*4d495c6eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(depth, 0, "submaps unimplemented");
86*4d495c6eSApple OSS Distributions
87*4d495c6eSApple OSS Distributions /*
88*4d495c6eSApple OSS Distributions * entry_start is mapped memory, and either
89*4d495c6eSApple OSS Distributions * (1) entry_start's mapping contains query_start, OR
90*4d495c6eSApple OSS Distributions * (2) query_start is unmapped and entry_start is the next mapped memory
91*4d495c6eSApple OSS Distributions */
92*4d495c6eSApple OSS Distributions
93*4d495c6eSApple OSS Distributions if (entry_start >= query_start + query_size) {
94*4d495c6eSApple OSS Distributions /*
95*4d495c6eSApple OSS Distributions * entry_start's mapping does not contain query_start,
96*4d495c6eSApple OSS Distributions * and entry_start's mapping begins after the query range,
97*4d495c6eSApple OSS Distributions * therefore the query range is a hole
98*4d495c6eSApple OSS Distributions */
99*4d495c6eSApple OSS Distributions return true;
100*4d495c6eSApple OSS Distributions } else {
101*4d495c6eSApple OSS Distributions return false;
102*4d495c6eSApple OSS Distributions }
103*4d495c6eSApple OSS Distributions }
104*4d495c6eSApple OSS Distributions
105*4d495c6eSApple OSS Distributions /* Call enable_exc_guard_of_type(), and test its behavior. */
106*4d495c6eSApple OSS Distributions static void
enable_exc_guard_of_type_and_verify(unsigned int guard_type)107*4d495c6eSApple OSS Distributions enable_exc_guard_of_type_and_verify(unsigned int guard_type)
108*4d495c6eSApple OSS Distributions {
109*4d495c6eSApple OSS Distributions struct {
110*4d495c6eSApple OSS Distributions const char *name;
111*4d495c6eSApple OSS Distributions task_exc_guard_behavior_t all_mask;
112*4d495c6eSApple OSS Distributions task_exc_guard_behavior_t deliver_mask;
113*4d495c6eSApple OSS Distributions task_exc_guard_behavior_t fatal_mask;
114*4d495c6eSApple OSS Distributions } guards[] = {
115*4d495c6eSApple OSS Distributions [GUARD_TYPE_VIRT_MEMORY] = {
116*4d495c6eSApple OSS Distributions .name = "VM",
117*4d495c6eSApple OSS Distributions .all_mask = TASK_EXC_GUARD_VM_ALL,
118*4d495c6eSApple OSS Distributions .deliver_mask = TASK_EXC_GUARD_VM_DELIVER,
119*4d495c6eSApple OSS Distributions .fatal_mask = TASK_EXC_GUARD_VM_FATAL
120*4d495c6eSApple OSS Distributions },
121*4d495c6eSApple OSS Distributions [GUARD_TYPE_MACH_PORT] = {
122*4d495c6eSApple OSS Distributions .name = "Mach port",
123*4d495c6eSApple OSS Distributions .all_mask = TASK_EXC_GUARD_MP_ALL,
124*4d495c6eSApple OSS Distributions .deliver_mask = TASK_EXC_GUARD_MP_DELIVER,
125*4d495c6eSApple OSS Distributions .fatal_mask = TASK_EXC_GUARD_MP_FATAL
126*4d495c6eSApple OSS Distributions }
127*4d495c6eSApple OSS Distributions };
128*4d495c6eSApple OSS Distributions
129*4d495c6eSApple OSS Distributions kern_return_t kr;
130*4d495c6eSApple OSS Distributions task_exc_guard_behavior_t disabling_behavior, old_behavior, new_behavior;
131*4d495c6eSApple OSS Distributions
132*4d495c6eSApple OSS Distributions T_QUIET; T_ASSERT_TRUE(guard_type < countof(guards) && guards[guard_type].name != NULL,
133*4d495c6eSApple OSS Distributions "guard type in enable_exc_guard_of_type_and_verify");
134*4d495c6eSApple OSS Distributions
135*4d495c6eSApple OSS Distributions /* disable guard exceptions of this type, then verify that enable_exc_guard_of_type enables them */
136*4d495c6eSApple OSS Distributions
137*4d495c6eSApple OSS Distributions kr = task_get_exc_guard_behavior(mach_task_self(), &disabling_behavior);
138*4d495c6eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "get old behavior");
139*4d495c6eSApple OSS Distributions disabling_behavior &= ~guards[guard_type].all_mask;
140*4d495c6eSApple OSS Distributions kr = task_set_exc_guard_behavior(mach_task_self(), disabling_behavior);
141*4d495c6eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "set empty behavior");
142*4d495c6eSApple OSS Distributions
143*4d495c6eSApple OSS Distributions old_behavior = enable_exc_guard_of_type(guard_type);
144*4d495c6eSApple OSS Distributions T_QUIET; T_ASSERT_EQ(old_behavior, disabling_behavior, "enable_exc_guard_of_type return value");
145*4d495c6eSApple OSS Distributions T_QUIET; T_ASSERT_FALSE(old_behavior & guards[guard_type].deliver_mask,
146*4d495c6eSApple OSS Distributions "%s guard exceptions must not be enabled", guards[guard_type].name);
147*4d495c6eSApple OSS Distributions
148*4d495c6eSApple OSS Distributions kr = task_get_exc_guard_behavior(mach_task_self(), &new_behavior);
149*4d495c6eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "get new behavior");
150*4d495c6eSApple OSS Distributions T_ASSERT_TRUE(new_behavior & guards[guard_type].deliver_mask,
151*4d495c6eSApple OSS Distributions "enable_exc_guard_of_type enabled %s guard exceptions", guards[guard_type].name);
152*4d495c6eSApple OSS Distributions T_ASSERT_FALSE(new_behavior & guards[guard_type].fatal_mask,
153*4d495c6eSApple OSS Distributions "enable_exc_guard_of_type set %s guard exceptions to non-fatal", guards[guard_type].name);
154*4d495c6eSApple OSS Distributions }
155*4d495c6eSApple OSS Distributions
156*4d495c6eSApple OSS Distributions
157*4d495c6eSApple OSS Distributions T_DECL(exc_guard_helper_test_vm,
158*4d495c6eSApple OSS Distributions "test the test helper function block_raised_exc_guard_of_type with VM guard exceptions")
159*4d495c6eSApple OSS Distributions {
160*4d495c6eSApple OSS Distributions if (process_is_translated()) {
161*4d495c6eSApple OSS Distributions T_SKIP("VM guard exceptions not supported on Rosetta (rdar://142438840)");
162*4d495c6eSApple OSS Distributions }
163*4d495c6eSApple OSS Distributions
164*4d495c6eSApple OSS Distributions kern_return_t kr;
165*4d495c6eSApple OSS Distributions exc_guard_helper_info_t exc_info;
166*4d495c6eSApple OSS Distributions
167*4d495c6eSApple OSS Distributions exc_guard_helper_init();
168*4d495c6eSApple OSS Distributions enable_exc_guard_of_type_and_verify(GUARD_TYPE_VIRT_MEMORY);
169*4d495c6eSApple OSS Distributions
170*4d495c6eSApple OSS Distributions /*
171*4d495c6eSApple OSS Distributions * Test guard exceptions by deallocating unallocated VM space.
172*4d495c6eSApple OSS Distributions * Problem: Rosetta asynchronously allocates memory in the process
173*4d495c6eSApple OSS Distributions * to store translated instructions. These allocations can land
174*4d495c6eSApple OSS Distributions * inside our unallocated space, disrupting our test and crashing
175*4d495c6eSApple OSS Distributions * after we call vm_deallocate() on space that we thought was empty.
176*4d495c6eSApple OSS Distributions * Solution:
177*4d495c6eSApple OSS Distributions * - use VM_FLAGS_RANDOM_ADDR in the hope of moving our allocation
178*4d495c6eSApple OSS Distributions * away from VM's ordinary next allocation space
179*4d495c6eSApple OSS Distributions * - try to verify that the unallocated space is empty before
180*4d495c6eSApple OSS Distributions * calling vm_deallocate, and retry several times if it is not empty
181*4d495c6eSApple OSS Distributions */
182*4d495c6eSApple OSS Distributions
183*4d495c6eSApple OSS Distributions #define LAST_RETRY 10
184*4d495c6eSApple OSS Distributions for (int retry_count = 0; retry_count <= LAST_RETRY; retry_count++) {
185*4d495c6eSApple OSS Distributions /* allocate three pages */
186*4d495c6eSApple OSS Distributions mach_vm_address_t allocated = 0;
187*4d495c6eSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(), &allocated, PAGE_SIZE * 3,
188*4d495c6eSApple OSS Distributions VM_FLAGS_ANYWHERE | VM_FLAGS_RANDOM_ADDR);
189*4d495c6eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "allocate space");
190*4d495c6eSApple OSS Distributions
191*4d495c6eSApple OSS Distributions /* deallocate the page in the middle; no EXC_GUARD from successful deallocation */
192*4d495c6eSApple OSS Distributions if (block_raised_exc_guard_of_type(GUARD_TYPE_VIRT_MEMORY, &exc_info, ^{
193*4d495c6eSApple OSS Distributions kern_return_t kr;
194*4d495c6eSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), allocated + PAGE_SIZE, PAGE_SIZE);
195*4d495c6eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "create hole");
196*4d495c6eSApple OSS Distributions })) {
197*4d495c6eSApple OSS Distributions T_FAIL("unexpected guard exception");
198*4d495c6eSApple OSS Distributions } else {
199*4d495c6eSApple OSS Distributions T_ASSERT_EQ(exc_info.catch_count, 0, "block_raised_exc_guard_of_type(VM) with no exceptions");
200*4d495c6eSApple OSS Distributions }
201*4d495c6eSApple OSS Distributions
202*4d495c6eSApple OSS Distributions /* try to deallocate the hole, twice, and detect the guard exceptions */
203*4d495c6eSApple OSS Distributions __block bool retry = false;
204*4d495c6eSApple OSS Distributions bool caught_exception = block_raised_exc_guard_of_type(GUARD_TYPE_VIRT_MEMORY, &exc_info, ^{
205*4d495c6eSApple OSS Distributions kern_return_t kr;
206*4d495c6eSApple OSS Distributions
207*4d495c6eSApple OSS Distributions /* deallocate page-hole-page; EXC_GUARD expected from deallocating a hole */
208*4d495c6eSApple OSS Distributions if (!is_hole(allocated + PAGE_SIZE, PAGE_SIZE)) {
209*4d495c6eSApple OSS Distributions retry = true; /* somebody allocated inside our unallocated space; retry */
210*4d495c6eSApple OSS Distributions return;
211*4d495c6eSApple OSS Distributions }
212*4d495c6eSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), allocated, PAGE_SIZE * 3);
213*4d495c6eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_deallocate a hole");
214*4d495c6eSApple OSS Distributions
215*4d495c6eSApple OSS Distributions /* deallocate again, now all holes; EXC_GUARD expected from deallocating a hole */
216*4d495c6eSApple OSS Distributions if (!is_hole(allocated, PAGE_SIZE * 3)) {
217*4d495c6eSApple OSS Distributions retry = true; /* somebody allocated inside our unallocated space; retry */
218*4d495c6eSApple OSS Distributions return;
219*4d495c6eSApple OSS Distributions }
220*4d495c6eSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), allocated, PAGE_SIZE * 3);
221*4d495c6eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_deallocate a hole again");
222*4d495c6eSApple OSS Distributions
223*4d495c6eSApple OSS Distributions if (!is_hole(allocated, PAGE_SIZE * 3)) {
224*4d495c6eSApple OSS Distributions retry = true; /* somebody allocated inside our unallocated space; retry */
225*4d495c6eSApple OSS Distributions return;
226*4d495c6eSApple OSS Distributions }
227*4d495c6eSApple OSS Distributions });
228*4d495c6eSApple OSS Distributions
229*4d495c6eSApple OSS Distributions if (retry) {
230*4d495c6eSApple OSS Distributions if (retry_count < LAST_RETRY) {
231*4d495c6eSApple OSS Distributions T_LOG("unallocated space was found to be allocated, retrying");
232*4d495c6eSApple OSS Distributions } else {
233*4d495c6eSApple OSS Distributions T_FAIL("intended unallocated space was repeatedly found to be allocated, giving up");
234*4d495c6eSApple OSS Distributions }
235*4d495c6eSApple OSS Distributions } else if (caught_exception) {
236*4d495c6eSApple OSS Distributions /* caught an exception as expected: verify what we caught */
237*4d495c6eSApple OSS Distributions T_ASSERT_EQ(exc_info.catch_count, 2, "block_raised_exc_guard_of_type(VM) with 2 exceptions");
238*4d495c6eSApple OSS Distributions T_ASSERT_EQ(exc_info.guard_type, GUARD_TYPE_VIRT_MEMORY, "caught exception's type");
239*4d495c6eSApple OSS Distributions T_ASSERT_EQ(exc_info.guard_flavor, kGUARD_EXC_DEALLOC_GAP, "caught exception's flavor");
240*4d495c6eSApple OSS Distributions T_ASSERT_EQ(exc_info.guard_payload, allocated + PAGE_SIZE, "caught exception's payload");
241*4d495c6eSApple OSS Distributions break; /* done retrying */
242*4d495c6eSApple OSS Distributions } else {
243*4d495c6eSApple OSS Distributions /* where's the beef? */
244*4d495c6eSApple OSS Distributions T_FAIL("no VM guard exception caught");
245*4d495c6eSApple OSS Distributions break; /* done retrying */
246*4d495c6eSApple OSS Distributions }
247*4d495c6eSApple OSS Distributions }
248*4d495c6eSApple OSS Distributions }
249*4d495c6eSApple OSS Distributions
250*4d495c6eSApple OSS Distributions
251*4d495c6eSApple OSS Distributions T_DECL(exc_guard_helper_test_mach_port,
252*4d495c6eSApple OSS Distributions "test the test helper function block_raised_exc_guard_of_type with Mach port guard exceptions")
253*4d495c6eSApple OSS Distributions {
254*4d495c6eSApple OSS Distributions kern_return_t kr;
255*4d495c6eSApple OSS Distributions exc_guard_helper_info_t exc_info;
256*4d495c6eSApple OSS Distributions mach_port_t port;
257*4d495c6eSApple OSS Distributions
258*4d495c6eSApple OSS Distributions exc_guard_helper_init();
259*4d495c6eSApple OSS Distributions enable_exc_guard_of_type_and_verify(GUARD_TYPE_MACH_PORT);
260*4d495c6eSApple OSS Distributions
261*4d495c6eSApple OSS Distributions /*
262*4d495c6eSApple OSS Distributions * Test guard exceptions by overflowing the send right count for a port.
263*4d495c6eSApple OSS Distributions */
264*4d495c6eSApple OSS Distributions
265*4d495c6eSApple OSS Distributions kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port);
266*4d495c6eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "new port");
267*4d495c6eSApple OSS Distributions kr = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND);
268*4d495c6eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "make send");
269*4d495c6eSApple OSS Distributions
270*4d495c6eSApple OSS Distributions /* add and remove one send right, should succeed */
271*4d495c6eSApple OSS Distributions if (block_raised_exc_guard_of_type(GUARD_TYPE_MACH_PORT, &exc_info, ^{
272*4d495c6eSApple OSS Distributions kern_return_t kr;
273*4d495c6eSApple OSS Distributions kr = mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_SEND, +1);
274*4d495c6eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "add one send right");
275*4d495c6eSApple OSS Distributions kr = mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_SEND, -1);
276*4d495c6eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "remove one send right");
277*4d495c6eSApple OSS Distributions })) {
278*4d495c6eSApple OSS Distributions T_FAIL("unexpected guard exception");
279*4d495c6eSApple OSS Distributions } else {
280*4d495c6eSApple OSS Distributions T_ASSERT_EQ(exc_info.catch_count, 0, "block_raised_exc_guard_of_type(MACH_PORT) with no exceptions");
281*4d495c6eSApple OSS Distributions }
282*4d495c6eSApple OSS Distributions
283*4d495c6eSApple OSS Distributions /* try to overflow the port's send right count, twice, and catch the exceptions */
284*4d495c6eSApple OSS Distributions bool caught_exception = block_raised_exc_guard_of_type(GUARD_TYPE_MACH_PORT, &exc_info, ^{
285*4d495c6eSApple OSS Distributions kern_return_t kr;
286*4d495c6eSApple OSS Distributions unsigned expected_error;
287*4d495c6eSApple OSS Distributions if (process_is_translated()) {
288*4d495c6eSApple OSS Distributions expected_error = 0x1000013; /* KERN_UREFS_OVERFLOW plus another bit? */
289*4d495c6eSApple OSS Distributions } else {
290*4d495c6eSApple OSS Distributions expected_error = KERN_INVALID_VALUE;
291*4d495c6eSApple OSS Distributions }
292*4d495c6eSApple OSS Distributions kr = mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_SEND, INT32_MAX);
293*4d495c6eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_ERROR(kr, expected_error, "add too many send rights");
294*4d495c6eSApple OSS Distributions kr = mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_SEND, INT32_MAX);
295*4d495c6eSApple OSS Distributions T_QUIET; T_ASSERT_MACH_ERROR(kr, expected_error, "add too many send rights, again");
296*4d495c6eSApple OSS Distributions });
297*4d495c6eSApple OSS Distributions if (caught_exception) {
298*4d495c6eSApple OSS Distributions /* caught an exception as expected: verify what we caught */
299*4d495c6eSApple OSS Distributions T_ASSERT_EQ(exc_info.catch_count, 2, "block_raised_exc_guard_of_type(MACH_PORT) with 2 exceptions");
300*4d495c6eSApple OSS Distributions T_ASSERT_EQ(exc_info.guard_type, GUARD_TYPE_MACH_PORT, "caught exception's type");
301*4d495c6eSApple OSS Distributions T_ASSERT_EQ(exc_info.guard_flavor, kGUARD_EXC_INVALID_VALUE, "caught exception's flavor");
302*4d495c6eSApple OSS Distributions T_ASSERT_EQ(exc_info.guard_target, port, "caught exception's target");
303*4d495c6eSApple OSS Distributions } else {
304*4d495c6eSApple OSS Distributions /* where's the beef? */
305*4d495c6eSApple OSS Distributions T_FAIL("no Mach port guard exception caught");
306*4d495c6eSApple OSS Distributions }
307*4d495c6eSApple OSS Distributions }
308