xref: /xnu-12377.1.9/tests/try_read_write_test.c (revision f6217f891ac0bb64f3d375211650a4c1ff8ca1ea)
1*f6217f89SApple OSS Distributions /*
2*f6217f89SApple OSS Distributions  * Copyright (c) 2024 Apple Inc. All rights reserved.
3*f6217f89SApple OSS Distributions  *
4*f6217f89SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*f6217f89SApple OSS Distributions  *
6*f6217f89SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*f6217f89SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*f6217f89SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*f6217f89SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*f6217f89SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*f6217f89SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*f6217f89SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*f6217f89SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*f6217f89SApple OSS Distributions  *
15*f6217f89SApple OSS Distributions  * Please obtain a copy of the License at
16*f6217f89SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*f6217f89SApple OSS Distributions  *
18*f6217f89SApple OSS Distributions  * The Original Code and all software distributed under the License are
19*f6217f89SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*f6217f89SApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*f6217f89SApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*f6217f89SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*f6217f89SApple OSS Distributions  * Please see the License for the specific language governing rights and
24*f6217f89SApple OSS Distributions  * limitations under the License.
25*f6217f89SApple OSS Distributions  *
26*f6217f89SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*f6217f89SApple OSS Distributions  */
28*f6217f89SApple OSS Distributions 
29*f6217f89SApple OSS Distributions /*
30*f6217f89SApple OSS Distributions  * try_read_write_test.c
31*f6217f89SApple OSS Distributions  *
32*f6217f89SApple OSS Distributions  * Test the testing helper functions in try_read_write.h.
33*f6217f89SApple OSS Distributions  */
34*f6217f89SApple OSS Distributions 
35*f6217f89SApple OSS Distributions #include <stdlib.h>
36*f6217f89SApple OSS Distributions #include <stdint.h>
37*f6217f89SApple OSS Distributions #include <stdbool.h>
38*f6217f89SApple OSS Distributions #include <darwintest.h>
39*f6217f89SApple OSS Distributions #include <mach/mach.h>
40*f6217f89SApple OSS Distributions #include <mach/mach_vm.h>
41*f6217f89SApple OSS Distributions #include <ptrauth.h>
42*f6217f89SApple OSS Distributions 
43*f6217f89SApple OSS Distributions #include "try_read_write.h"
44*f6217f89SApple OSS Distributions 
45*f6217f89SApple OSS Distributions T_GLOBAL_META(
46*f6217f89SApple OSS Distributions 	T_META_NAMESPACE("xnu"),
47*f6217f89SApple OSS Distributions 	T_META_RADAR_COMPONENT_NAME("xnu"),
48*f6217f89SApple OSS Distributions 	T_META_RADAR_COMPONENT_VERSION("vm"),
49*f6217f89SApple OSS Distributions 	T_META_RUN_CONCURRENTLY(true),
50*f6217f89SApple OSS Distributions 	T_META_ALL_VALID_ARCHS(true)
51*f6217f89SApple OSS Distributions 	);
52*f6217f89SApple OSS Distributions 
53*f6217f89SApple OSS Distributions #define MAYBE_QUIET(quiet) \
54*f6217f89SApple OSS Distributions 	do {                                    \
55*f6217f89SApple OSS Distributions 	        if (quiet) {                    \
56*f6217f89SApple OSS Distributions 	                T_QUIET;                \
57*f6217f89SApple OSS Distributions 	        }                               \
58*f6217f89SApple OSS Distributions 	} while (0)
59*f6217f89SApple OSS Distributions 
60*f6217f89SApple OSS Distributions static void
test_try_read_byte_maybe_quietly(mach_vm_address_t addr,uint8_t expected_byte,kern_return_t expected_error,bool quiet,const char * message)61*f6217f89SApple OSS Distributions test_try_read_byte_maybe_quietly(
62*f6217f89SApple OSS Distributions 	mach_vm_address_t addr,
63*f6217f89SApple OSS Distributions 	uint8_t expected_byte,
64*f6217f89SApple OSS Distributions 	kern_return_t expected_error,
65*f6217f89SApple OSS Distributions 	bool quiet,
66*f6217f89SApple OSS Distributions 	const char *message)
67*f6217f89SApple OSS Distributions {
68*f6217f89SApple OSS Distributions 	bool expected_result = (expected_error == 0);
69*f6217f89SApple OSS Distributions 	bool actual_result;
70*f6217f89SApple OSS Distributions 	uint8_t actual_byte;
71*f6217f89SApple OSS Distributions 	kern_return_t actual_error;
72*f6217f89SApple OSS Distributions 
73*f6217f89SApple OSS Distributions 	actual_result = try_read_byte(addr, &actual_byte, &actual_error);
74*f6217f89SApple OSS Distributions 
75*f6217f89SApple OSS Distributions 	MAYBE_QUIET(quiet); T_EXPECT_EQ(expected_result, actual_result, "%s: try_read_byte return value", message);
76*f6217f89SApple OSS Distributions 	MAYBE_QUIET(quiet); T_EXPECT_EQ(expected_error, actual_error, "%s: try_read_byte error code", message);
77*f6217f89SApple OSS Distributions 	if (expected_error == 0 && actual_error == 0) {
78*f6217f89SApple OSS Distributions 		MAYBE_QUIET(quiet); T_EXPECT_EQ(expected_byte, actual_byte, "%s: try_read_byte value read", message);
79*f6217f89SApple OSS Distributions 	}
80*f6217f89SApple OSS Distributions }
81*f6217f89SApple OSS Distributions 
82*f6217f89SApple OSS Distributions static void
test_try_read_byte(mach_vm_address_t addr,uint8_t expected_byte,kern_return_t expected_error,const char * message)83*f6217f89SApple OSS Distributions test_try_read_byte(
84*f6217f89SApple OSS Distributions 	mach_vm_address_t addr,
85*f6217f89SApple OSS Distributions 	uint8_t expected_byte,
86*f6217f89SApple OSS Distributions 	kern_return_t expected_error,
87*f6217f89SApple OSS Distributions 	const char *message)
88*f6217f89SApple OSS Distributions {
89*f6217f89SApple OSS Distributions 	test_try_read_byte_maybe_quietly(addr, expected_byte, expected_error, false /* quiet */, message);
90*f6217f89SApple OSS Distributions }
91*f6217f89SApple OSS Distributions 
92*f6217f89SApple OSS Distributions static void
test_try_read_byte_quietly(mach_vm_address_t addr,uint8_t expected_byte,kern_return_t expected_error,const char * message)93*f6217f89SApple OSS Distributions test_try_read_byte_quietly(
94*f6217f89SApple OSS Distributions 	mach_vm_address_t addr,
95*f6217f89SApple OSS Distributions 	uint8_t expected_byte,
96*f6217f89SApple OSS Distributions 	kern_return_t expected_error,
97*f6217f89SApple OSS Distributions 	const char *message)
98*f6217f89SApple OSS Distributions {
99*f6217f89SApple OSS Distributions 	test_try_read_byte_maybe_quietly(addr, expected_byte, expected_error, true /* quiet */, message);
100*f6217f89SApple OSS Distributions }
101*f6217f89SApple OSS Distributions 
102*f6217f89SApple OSS Distributions static void
test_try_write_byte_maybe_quietly(mach_vm_address_t addr,uint8_t expected_byte,kern_return_t expected_error,bool quiet,const char * message)103*f6217f89SApple OSS Distributions test_try_write_byte_maybe_quietly(
104*f6217f89SApple OSS Distributions 	mach_vm_address_t addr,
105*f6217f89SApple OSS Distributions 	uint8_t expected_byte,
106*f6217f89SApple OSS Distributions 	kern_return_t expected_error,
107*f6217f89SApple OSS Distributions 	bool quiet,
108*f6217f89SApple OSS Distributions 	const char *message)
109*f6217f89SApple OSS Distributions {
110*f6217f89SApple OSS Distributions 	bool expected_result = (expected_error == 0);
111*f6217f89SApple OSS Distributions 	bool actual_result;
112*f6217f89SApple OSS Distributions 	uint8_t actual_byte;
113*f6217f89SApple OSS Distributions 	kern_return_t actual_error;
114*f6217f89SApple OSS Distributions 
115*f6217f89SApple OSS Distributions 	actual_result = try_write_byte(addr, expected_byte, &actual_error);
116*f6217f89SApple OSS Distributions 
117*f6217f89SApple OSS Distributions 	MAYBE_QUIET(quiet); T_EXPECT_EQ(expected_result, actual_result, "%s: try_write_byte return value", message);
118*f6217f89SApple OSS Distributions 	MAYBE_QUIET(quiet); T_EXPECT_EQ(expected_error, actual_error, "%s: try_write_byte error code", message);
119*f6217f89SApple OSS Distributions 	if (expected_error == 0 && actual_error == 0) {
120*f6217f89SApple OSS Distributions 		actual_byte = *(volatile uint8_t *)addr;
121*f6217f89SApple OSS Distributions 		MAYBE_QUIET(quiet); T_EXPECT_EQ(expected_byte, actual_byte, "%s: try_write_byte value written", message);
122*f6217f89SApple OSS Distributions 	}
123*f6217f89SApple OSS Distributions }
124*f6217f89SApple OSS Distributions 
125*f6217f89SApple OSS Distributions static void
test_try_write_byte(mach_vm_address_t addr,uint8_t expected_byte,kern_return_t expected_error,const char * message)126*f6217f89SApple OSS Distributions test_try_write_byte(
127*f6217f89SApple OSS Distributions 	mach_vm_address_t addr,
128*f6217f89SApple OSS Distributions 	uint8_t expected_byte,
129*f6217f89SApple OSS Distributions 	kern_return_t expected_error,
130*f6217f89SApple OSS Distributions 	const char *message)
131*f6217f89SApple OSS Distributions {
132*f6217f89SApple OSS Distributions 	test_try_write_byte_maybe_quietly(addr, expected_byte, expected_error, false /* quiet */, message);
133*f6217f89SApple OSS Distributions }
134*f6217f89SApple OSS Distributions 
135*f6217f89SApple OSS Distributions static void
test_try_write_byte_quietly(mach_vm_address_t addr,uint8_t expected_byte,kern_return_t expected_error,const char * message)136*f6217f89SApple OSS Distributions test_try_write_byte_quietly(
137*f6217f89SApple OSS Distributions 	mach_vm_address_t addr,
138*f6217f89SApple OSS Distributions 	uint8_t expected_byte,
139*f6217f89SApple OSS Distributions 	kern_return_t expected_error,
140*f6217f89SApple OSS Distributions 	const char *message)
141*f6217f89SApple OSS Distributions {
142*f6217f89SApple OSS Distributions 	test_try_write_byte_maybe_quietly(addr, expected_byte, expected_error, true /* quiet */, message);
143*f6217f89SApple OSS Distributions }
144*f6217f89SApple OSS Distributions 
145*f6217f89SApple OSS Distributions static mach_vm_address_t
allocate_page_with_prot(vm_prot_t prot)146*f6217f89SApple OSS Distributions allocate_page_with_prot(vm_prot_t prot)
147*f6217f89SApple OSS Distributions {
148*f6217f89SApple OSS Distributions 	mach_vm_address_t addr;
149*f6217f89SApple OSS Distributions 	kern_return_t kr;
150*f6217f89SApple OSS Distributions 
151*f6217f89SApple OSS Distributions 	kr = mach_vm_allocate(mach_task_self(), &addr, PAGE_SIZE, VM_FLAGS_ANYWHERE);
152*f6217f89SApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_allocate");
153*f6217f89SApple OSS Distributions 	kr = mach_vm_protect(mach_task_self(), addr, PAGE_SIZE, false /* set max */, prot);
154*f6217f89SApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_protect");
155*f6217f89SApple OSS Distributions 	return addr;
156*f6217f89SApple OSS Distributions }
157*f6217f89SApple OSS Distributions 
158*f6217f89SApple OSS Distributions static void
deallocate_page(mach_vm_address_t addr)159*f6217f89SApple OSS Distributions deallocate_page(mach_vm_address_t addr)
160*f6217f89SApple OSS Distributions {
161*f6217f89SApple OSS Distributions 	kern_return_t kr = mach_vm_deallocate(mach_task_self(), addr, PAGE_SIZE);
162*f6217f89SApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_deallocate");
163*f6217f89SApple OSS Distributions }
164*f6217f89SApple OSS Distributions 
165*f6217f89SApple OSS Distributions /*
166*f6217f89SApple OSS Distributions  * Generate some r-x memory with a known value.
167*f6217f89SApple OSS Distributions  */
168*f6217f89SApple OSS Distributions static void __attribute__((naked))
instruction_byte_ff(void)169*f6217f89SApple OSS Distributions instruction_byte_ff(void)
170*f6217f89SApple OSS Distributions {
171*f6217f89SApple OSS Distributions 	asm(".quad 0xffffffff");
172*f6217f89SApple OSS Distributions }
173*f6217f89SApple OSS Distributions 
174*f6217f89SApple OSS Distributions T_DECL(try_read_write_test,
175*f6217f89SApple OSS Distributions     "test the test helper functions try_read_byte and try_write_byte")
176*f6217f89SApple OSS Distributions {
177*f6217f89SApple OSS Distributions 	mach_vm_address_t addr;
178*f6217f89SApple OSS Distributions 
179*f6217f89SApple OSS Distributions 	/* read and write an unmapped address */
180*f6217f89SApple OSS Distributions 	test_try_read_byte(0, 0, KERN_INVALID_ADDRESS, "read unmapped address");
181*f6217f89SApple OSS Distributions 	test_try_write_byte(0, 0, KERN_INVALID_ADDRESS, "write unmapped address");
182*f6217f89SApple OSS Distributions 
183*f6217f89SApple OSS Distributions 	/* read and write --- */
184*f6217f89SApple OSS Distributions 	addr = allocate_page_with_prot(VM_PROT_NONE);
185*f6217f89SApple OSS Distributions 	test_try_read_byte(addr, 0, KERN_PROTECTION_FAILURE, "read prot ---");
186*f6217f89SApple OSS Distributions 	test_try_write_byte(addr, 1, KERN_PROTECTION_FAILURE, "write prot ---");
187*f6217f89SApple OSS Distributions 	deallocate_page(addr);
188*f6217f89SApple OSS Distributions 
189*f6217f89SApple OSS Distributions 	/* read and write r-- */
190*f6217f89SApple OSS Distributions 	addr = allocate_page_with_prot(VM_PROT_READ);
191*f6217f89SApple OSS Distributions 	test_try_read_byte(addr, 0, KERN_SUCCESS, "read prot r--");
192*f6217f89SApple OSS Distributions 	test_try_write_byte(addr, 1, KERN_PROTECTION_FAILURE, "write prot r--");
193*f6217f89SApple OSS Distributions 	deallocate_page(addr);
194*f6217f89SApple OSS Distributions 
195*f6217f89SApple OSS Distributions 	/* read and write -w- */
196*f6217f89SApple OSS Distributions 	addr = allocate_page_with_prot(VM_PROT_WRITE);
197*f6217f89SApple OSS Distributions 	test_try_read_byte(addr, 0, KERN_PROTECTION_FAILURE, "read prot -w-");
198*f6217f89SApple OSS Distributions 	test_try_write_byte(addr, 1, KERN_PROTECTION_FAILURE, "write prot -w-");
199*f6217f89SApple OSS Distributions 	deallocate_page(addr);
200*f6217f89SApple OSS Distributions 
201*f6217f89SApple OSS Distributions 	/* read and write rw- */
202*f6217f89SApple OSS Distributions 	addr = allocate_page_with_prot(VM_PROT_READ | VM_PROT_WRITE);
203*f6217f89SApple OSS Distributions 	*(uint8_t *)addr = 1;
204*f6217f89SApple OSS Distributions 	test_try_read_byte(addr, 1, KERN_SUCCESS, "read prot rw-");
205*f6217f89SApple OSS Distributions 	test_try_write_byte(addr, 2, KERN_SUCCESS, "write prot rw-");
206*f6217f89SApple OSS Distributions 	test_try_read_byte(addr, 2, KERN_SUCCESS, "read prot rw- again");
207*f6217f89SApple OSS Distributions 	deallocate_page(addr);
208*f6217f89SApple OSS Distributions 
209*f6217f89SApple OSS Distributions 	/* read and write r-x */
210*f6217f89SApple OSS Distributions 	addr = (mach_vm_address_t)ptrauth_strip(&instruction_byte_ff, ptrauth_key_function_pointer);
211*f6217f89SApple OSS Distributions 	test_try_read_byte(addr, 0xff, KERN_SUCCESS, "read prot r-x");
212*f6217f89SApple OSS Distributions 	test_try_write_byte(addr, 1, KERN_PROTECTION_FAILURE, "write prot r-x");
213*f6217f89SApple OSS Distributions }
214*f6217f89SApple OSS Distributions 
215*f6217f89SApple OSS Distributions 
216*f6217f89SApple OSS Distributions /* this test provokes THREAD_COUNT * REP_COUNT * PAGE_SIZE exceptions */
217*f6217f89SApple OSS Distributions #define THREAD_COUNT 10
218*f6217f89SApple OSS Distributions #define REP_COUNT 5
219*f6217f89SApple OSS Distributions 
220*f6217f89SApple OSS Distributions struct test_alloc {
221*f6217f89SApple OSS Distributions 	mach_vm_address_t addr;
222*f6217f89SApple OSS Distributions 	vm_prot_t prot;
223*f6217f89SApple OSS Distributions 	kern_return_t expected_read_error;
224*f6217f89SApple OSS Distributions 	kern_return_t expected_write_error;
225*f6217f89SApple OSS Distributions };
226*f6217f89SApple OSS Distributions 
227*f6217f89SApple OSS Distributions static struct test_alloc
allocate_page_with_random_prot(void)228*f6217f89SApple OSS Distributions allocate_page_with_random_prot(void)
229*f6217f89SApple OSS Distributions {
230*f6217f89SApple OSS Distributions 	struct test_alloc result;
231*f6217f89SApple OSS Distributions 
232*f6217f89SApple OSS Distributions 	switch (random() % 4) {
233*f6217f89SApple OSS Distributions 	case 0:
234*f6217f89SApple OSS Distributions 		result.prot = VM_PROT_NONE;
235*f6217f89SApple OSS Distributions 		result.expected_read_error  = KERN_PROTECTION_FAILURE;
236*f6217f89SApple OSS Distributions 		result.expected_write_error = KERN_PROTECTION_FAILURE;
237*f6217f89SApple OSS Distributions 		break;
238*f6217f89SApple OSS Distributions 	case 1:
239*f6217f89SApple OSS Distributions 		result.prot = VM_PROT_READ;
240*f6217f89SApple OSS Distributions 		result.expected_read_error  = KERN_SUCCESS;
241*f6217f89SApple OSS Distributions 		result.expected_write_error = KERN_PROTECTION_FAILURE;
242*f6217f89SApple OSS Distributions 		break;
243*f6217f89SApple OSS Distributions 	case 2:
244*f6217f89SApple OSS Distributions 		result.prot = VM_PROT_WRITE;
245*f6217f89SApple OSS Distributions 		result.expected_read_error  = KERN_PROTECTION_FAILURE;
246*f6217f89SApple OSS Distributions 		result.expected_write_error = KERN_PROTECTION_FAILURE;
247*f6217f89SApple OSS Distributions 		break;
248*f6217f89SApple OSS Distributions 	case 3:
249*f6217f89SApple OSS Distributions 		result.prot = VM_PROT_READ | VM_PROT_WRITE;
250*f6217f89SApple OSS Distributions 		result.expected_read_error  = KERN_SUCCESS;
251*f6217f89SApple OSS Distributions 		result.expected_write_error = KERN_SUCCESS;
252*f6217f89SApple OSS Distributions 		break;
253*f6217f89SApple OSS Distributions 	}
254*f6217f89SApple OSS Distributions 
255*f6217f89SApple OSS Distributions 	result.addr = allocate_page_with_prot(result.prot);
256*f6217f89SApple OSS Distributions 	return result;
257*f6217f89SApple OSS Distributions }
258*f6217f89SApple OSS Distributions 
259*f6217f89SApple OSS Distributions static void *
multithreaded_test(void * arg)260*f6217f89SApple OSS Distributions multithreaded_test(void *arg)
261*f6217f89SApple OSS Distributions {
262*f6217f89SApple OSS Distributions 	struct test_alloc alloc = *(struct test_alloc *)arg;
263*f6217f89SApple OSS Distributions 
264*f6217f89SApple OSS Distributions 	/* Read and write a lot from our page. */
265*f6217f89SApple OSS Distributions 	for (int reps = 0; reps < REP_COUNT; reps++) {
266*f6217f89SApple OSS Distributions 		for (int offset = 0; offset < PAGE_SIZE; offset++) {
267*f6217f89SApple OSS Distributions 			test_try_read_byte_quietly(alloc.addr + offset, 0, alloc.expected_read_error, "thread read");
268*f6217f89SApple OSS Distributions 			test_try_write_byte_quietly(alloc.addr + offset, 0, alloc.expected_write_error, "thread write");
269*f6217f89SApple OSS Distributions 		}
270*f6217f89SApple OSS Distributions 	}
271*f6217f89SApple OSS Distributions 
272*f6217f89SApple OSS Distributions 	return NULL;
273*f6217f89SApple OSS Distributions }
274*f6217f89SApple OSS Distributions 
275*f6217f89SApple OSS Distributions T_DECL(try_read_write_test_multithreaded,
276*f6217f89SApple OSS Distributions     "test try_read_byte and try_write_byte from multiple threads")
277*f6217f89SApple OSS Distributions {
278*f6217f89SApple OSS Distributions 	verbose_exc_helper = false;
279*f6217f89SApple OSS Distributions 
280*f6217f89SApple OSS Distributions 	pthread_t threads[THREAD_COUNT];
281*f6217f89SApple OSS Distributions 	struct test_alloc allocs[THREAD_COUNT];
282*f6217f89SApple OSS Distributions 
283*f6217f89SApple OSS Distributions 	/* each thread gets a page with a random prot to read and write on */
284*f6217f89SApple OSS Distributions 
285*f6217f89SApple OSS Distributions 	for (int i = 0; i < THREAD_COUNT; i++) {
286*f6217f89SApple OSS Distributions 		allocs[i] = allocate_page_with_random_prot();
287*f6217f89SApple OSS Distributions 	}
288*f6217f89SApple OSS Distributions 
289*f6217f89SApple OSS Distributions 	T_LOG("running %d threads each %d times", THREAD_COUNT, REP_COUNT);
290*f6217f89SApple OSS Distributions 
291*f6217f89SApple OSS Distributions 	for (int i = 0; i < THREAD_COUNT; i++) {
292*f6217f89SApple OSS Distributions 		pthread_create(&threads[i], NULL, multithreaded_test, &allocs[i]);
293*f6217f89SApple OSS Distributions 	}
294*f6217f89SApple OSS Distributions 
295*f6217f89SApple OSS Distributions 	for (int i = 0; i < THREAD_COUNT; i++) {
296*f6217f89SApple OSS Distributions 		pthread_join(threads[i], NULL);
297*f6217f89SApple OSS Distributions 		deallocate_page(allocs[i].addr);
298*f6217f89SApple OSS Distributions 	}
299*f6217f89SApple OSS Distributions }
300