xref: /xnu-8792.81.2/tests/test_sysctl_kern_procargs_25397314.m (revision 19c3b8c28c31cb8130e034cfb5df6bf9ba342d90)
1*19c3b8c2SApple OSS Distributions#include <Foundation/Foundation.h>
2*19c3b8c2SApple OSS Distributions#include <darwintest.h>
3*19c3b8c2SApple OSS Distributions#include <darwintest_utils.h>
4*19c3b8c2SApple OSS Distributions#include <mach-o/dyld.h>
5*19c3b8c2SApple OSS Distributions#include <System/sys/codesign.h>
6*19c3b8c2SApple OSS Distributions#include <unistd.h>
7*19c3b8c2SApple OSS Distributions#include <stdlib.h>
8*19c3b8c2SApple OSS Distributions#include <signal.h>
9*19c3b8c2SApple OSS Distributions#include <sys/types.h>
10*19c3b8c2SApple OSS Distributions#include <sys/sysctl.h>
11*19c3b8c2SApple OSS Distributions
12*19c3b8c2SApple OSS Distributions
13*19c3b8c2SApple OSS DistributionsT_GLOBAL_META(T_META_RUN_CONCURRENTLY(true),
14*19c3b8c2SApple OSS Distributions    T_META_ASROOT(true));
15*19c3b8c2SApple OSS Distributions
16*19c3b8c2SApple OSS Distributionsstruct procargs {
17*19c3b8c2SApple OSS Distributions	int argc;
18*19c3b8c2SApple OSS Distributions	size_t preflightSize;
19*19c3b8c2SApple OSS Distributions	NSString *executablePath;
20*19c3b8c2SApple OSS Distributions	NSArray *components;
21*19c3b8c2SApple OSS Distributions	NSString *legacyExecutablePath;
22*19c3b8c2SApple OSS Distributions	void *rawBuffer;
23*19c3b8c2SApple OSS Distributions	size_t rawBufferSize;
24*19c3b8c2SApple OSS Distributions};
25*19c3b8c2SApple OSS Distributions
26*19c3b8c2SApple OSS Distributionsstatic void printHexDump(void* buffer, size_t size);
27*19c3b8c2SApple OSS Distributions
28*19c3b8c2SApple OSS Distributionstypedef struct procargs *procargs_t;
29*19c3b8c2SApple OSS Distributions
30*19c3b8c2SApple OSS Distributions#define TEST_ENVIRONMENT_VARIABLE       "TESTENVVARIABLE"
31*19c3b8c2SApple OSS Distributions#define TEST_ENVIRONMENT_VARIABLE_VALUE "TESTENVVARIABLE_VALUE"
32*19c3b8c2SApple OSS Distributions
33*19c3b8c2SApple OSS Distributions
34*19c3b8c2SApple OSS Distributionsstatic size_t argmax;
35*19c3b8c2SApple OSS Distributions
36*19c3b8c2SApple OSS Distributionsstatic procargs_t getProcArgs(int type, pid_t pid, size_t allocSize)
37*19c3b8c2SApple OSS Distributions{
38*19c3b8c2SApple OSS Distributions	int sysctlArgs[3] = {CTL_KERN, type, pid};
39*19c3b8c2SApple OSS Distributions	int argc;
40*19c3b8c2SApple OSS Distributions	NSMutableArray *components = [NSMutableArray array];
41*19c3b8c2SApple OSS Distributions	procargs_t args = (procargs_t) malloc(sizeof(struct procargs));
42*19c3b8c2SApple OSS Distributions	size_t currentLen = 0;
43*19c3b8c2SApple OSS Distributions	bool legacyPathPresent = false;
44*19c3b8c2SApple OSS Distributions	NSString *current = nil;
45*19c3b8c2SApple OSS Distributions	NSString *legacyExecutablePath = nil;
46*19c3b8c2SApple OSS Distributions	NSString *executablePath = nil;
47*19c3b8c2SApple OSS Distributions	size_t bufferSize;
48*19c3b8c2SApple OSS Distributions	size_t preflightSize = 0;
49*19c3b8c2SApple OSS Distributions	const char *name = type == KERN_PROCARGS ? "KERN_PROCARGS" : "KERN_PROCARGS2";
50*19c3b8c2SApple OSS Distributions	const char *cursor;
51*19c3b8c2SApple OSS Distributions	void *buffer;
52*19c3b8c2SApple OSS Distributions
53*19c3b8c2SApple OSS Distributions	T_LOG("Get proc args for pid %d, allocSize %lu with %s", pid, allocSize, name);
54*19c3b8c2SApple OSS Distributions
55*19c3b8c2SApple OSS Distributions
56*19c3b8c2SApple OSS Distributions	T_ASSERT_TRUE(type == KERN_PROCARGS || type == KERN_PROCARGS2, "type is valid");
57*19c3b8c2SApple OSS Distributions
58*19c3b8c2SApple OSS Distributions	/* Determine how much memory to allocate. If allocSize is 0 we will use the size
59*19c3b8c2SApple OSS Distributions	 * we get from the sysctl for our buffer. */
60*19c3b8c2SApple OSS Distributions	T_ASSERT_POSIX_SUCCESS(sysctl(sysctlArgs, 3, NULL, &preflightSize, NULL, 0), "sysctl %s", name);
61*19c3b8c2SApple OSS Distributions	T_LOG("procargs data should be %lu bytes", preflightSize);
62*19c3b8c2SApple OSS Distributions
63*19c3b8c2SApple OSS Distributions	if (allocSize == 0) {
64*19c3b8c2SApple OSS Distributions		allocSize = preflightSize;
65*19c3b8c2SApple OSS Distributions	}
66*19c3b8c2SApple OSS Distributions
67*19c3b8c2SApple OSS Distributions	buffer = malloc(allocSize);
68*19c3b8c2SApple OSS Distributions	T_QUIET; T_ASSERT_NOTNULL(buffer, "malloc buffer of size %lu", allocSize);
69*19c3b8c2SApple OSS Distributions	bufferSize = allocSize;
70*19c3b8c2SApple OSS Distributions
71*19c3b8c2SApple OSS Distributions	T_ASSERT_POSIX_SUCCESS(sysctl(sysctlArgs, 3, buffer, &bufferSize, NULL, 0), "sysctl %s", name);
72*19c3b8c2SApple OSS Distributions	T_ASSERT_LE(bufferSize, allocSize, "returned buffer size should be less than allocated size");
73*19c3b8c2SApple OSS Distributions	T_LOG("sysctl wrote %lu bytes", bufferSize);
74*19c3b8c2SApple OSS Distributions	if (allocSize >= bufferSize) {
75*19c3b8c2SApple OSS Distributions		/* Allocated buffer is larger than what kernel wrote, so it should match preflightSize */
76*19c3b8c2SApple OSS Distributions		T_ASSERT_EQ(bufferSize, preflightSize, "buffer size should be the same as preflight size");
77*19c3b8c2SApple OSS Distributions	}
78*19c3b8c2SApple OSS Distributions
79*19c3b8c2SApple OSS Distributions	printHexDump(buffer, bufferSize);
80*19c3b8c2SApple OSS Distributions
81*19c3b8c2SApple OSS Distributions	if (type == KERN_PROCARGS2) {
82*19c3b8c2SApple OSS Distributions		argc = *(int *)buffer;
83*19c3b8c2SApple OSS Distributions		cursor = (const char *)buffer + sizeof(int);
84*19c3b8c2SApple OSS Distributions	} else {
85*19c3b8c2SApple OSS Distributions		/* Without KERN_PROCARGS2, we can't tell where argv ends and environ begins.
86*19c3b8c2SApple OSS Distributions		 * Set argc to -1 to indicate this */
87*19c3b8c2SApple OSS Distributions		argc = -1;
88*19c3b8c2SApple OSS Distributions		cursor = buffer;
89*19c3b8c2SApple OSS Distributions	}
90*19c3b8c2SApple OSS Distributions
91*19c3b8c2SApple OSS Distributions	while ((uintptr_t)cursor < (uintptr_t)buffer + bufferSize) {
92*19c3b8c2SApple OSS Distributions		/* Ensure alignment and check if the uint16_t at cursor is the magic value */
93*19c3b8c2SApple OSS Distributions		if (!((uintptr_t)cursor & (sizeof(uint16_t) - 1)) &&
94*19c3b8c2SApple OSS Distributions			(uintptr_t)buffer + bufferSize - (uintptr_t)cursor > sizeof(uint16_t)) {
95*19c3b8c2SApple OSS Distributions			/* Silence -Wcast-align by casting to const void * */
96*19c3b8c2SApple OSS Distributions			uint16_t value = *(const uint16_t *)(const void *)cursor;
97*19c3b8c2SApple OSS Distributions			if (value == 0xBFFF) {
98*19c3b8c2SApple OSS Distributions				/* Magic value that specifies the end of the argument/environ section */
99*19c3b8c2SApple OSS Distributions				cursor += sizeof(uint16_t) + sizeof(uint32_t);
100*19c3b8c2SApple OSS Distributions				legacyPathPresent = true;
101*19c3b8c2SApple OSS Distributions				break;
102*19c3b8c2SApple OSS Distributions			}
103*19c3b8c2SApple OSS Distributions		}
104*19c3b8c2SApple OSS Distributions		currentLen = strnlen(cursor, bufferSize - ((uintptr_t)cursor - (uintptr_t)buffer));
105*19c3b8c2SApple OSS Distributions		current = [[NSString alloc] initWithBytes:cursor length:currentLen encoding:NSUTF8StringEncoding];
106*19c3b8c2SApple OSS Distributions		T_QUIET; T_ASSERT_NOTNULL(current, "allocated string");
107*19c3b8c2SApple OSS Distributions		cursor += currentLen + 1;
108*19c3b8c2SApple OSS Distributions
109*19c3b8c2SApple OSS Distributions		if (executablePath == nil) {
110*19c3b8c2SApple OSS Distributions			executablePath = current;
111*19c3b8c2SApple OSS Distributions			[executablePath retain];
112*19c3b8c2SApple OSS Distributions			while (*cursor == 0) {
113*19c3b8c2SApple OSS Distributions				cursor++;
114*19c3b8c2SApple OSS Distributions			}
115*19c3b8c2SApple OSS Distributions		} else {
116*19c3b8c2SApple OSS Distributions			[components addObject:current];
117*19c3b8c2SApple OSS Distributions		}
118*19c3b8c2SApple OSS Distributions		[current release];
119*19c3b8c2SApple OSS Distributions	}
120*19c3b8c2SApple OSS Distributions	if (legacyPathPresent) {
121*19c3b8c2SApple OSS Distributions		T_ASSERT_EQ(type, KERN_PROCARGS, "Legacy executable path should only be present for KERN_PROCARGS");
122*19c3b8c2SApple OSS Distributions		currentLen = strnlen(cursor, bufferSize - ((uintptr_t)cursor - (uintptr_t)buffer));
123*19c3b8c2SApple OSS Distributions		current = [[NSString alloc] initWithBytes:cursor length:currentLen encoding:NSUTF8StringEncoding];
124*19c3b8c2SApple OSS Distributions		T_QUIET; T_ASSERT_NOTNULL(current, "allocated string");
125*19c3b8c2SApple OSS Distributions		legacyExecutablePath = current;
126*19c3b8c2SApple OSS Distributions	}
127*19c3b8c2SApple OSS Distributions	args->argc = argc;
128*19c3b8c2SApple OSS Distributions	args->executablePath = executablePath;
129*19c3b8c2SApple OSS Distributions	args->components = components;
130*19c3b8c2SApple OSS Distributions	args->legacyExecutablePath = legacyExecutablePath;
131*19c3b8c2SApple OSS Distributions	args->preflightSize = preflightSize;
132*19c3b8c2SApple OSS Distributions	args->rawBuffer = buffer;
133*19c3b8c2SApple OSS Distributions	args->rawBufferSize = bufferSize;
134*19c3b8c2SApple OSS Distributions	return args;
135*19c3b8c2SApple OSS Distributions}
136*19c3b8c2SApple OSS Distributions
137*19c3b8c2SApple OSS Distributionsstatic void printProcArgs(procargs_t procargs) {
138*19c3b8c2SApple OSS Distributions	if (procargs->argc == -1) {
139*19c3b8c2SApple OSS Distributions		T_LOG("No argument count");
140*19c3b8c2SApple OSS Distributions	} else {
141*19c3b8c2SApple OSS Distributions		T_LOG("Argc is %d", procargs->argc);
142*19c3b8c2SApple OSS Distributions	}
143*19c3b8c2SApple OSS Distributions	T_LOG("Executable path: %s (length %lu)", [procargs->executablePath UTF8String], [procargs->executablePath length]);
144*19c3b8c2SApple OSS Distributions	for (size_t i = 0; i < [procargs->components count]; i++) {
145*19c3b8c2SApple OSS Distributions		NSString *component = [procargs->components objectAtIndex:i];
146*19c3b8c2SApple OSS Distributions		const char *str = [component UTF8String];
147*19c3b8c2SApple OSS Distributions		size_t len = [component length];
148*19c3b8c2SApple OSS Distributions		if (procargs->argc != -1) {
149*19c3b8c2SApple OSS Distributions			T_LOG("%s %zu: %s (length %lu)", i >= (size_t)procargs->argc ? "Env var" : "Argument", i, str, len);
150*19c3b8c2SApple OSS Distributions		} else {
151*19c3b8c2SApple OSS Distributions			T_LOG("Component %zu: %s (length %lu)", i, str, len);
152*19c3b8c2SApple OSS Distributions		}
153*19c3b8c2SApple OSS Distributions	}
154*19c3b8c2SApple OSS Distributions	if (procargs->legacyExecutablePath) {
155*19c3b8c2SApple OSS Distributions		T_LOG("Contains legacy executable path: %s (length %lu)", [procargs->legacyExecutablePath UTF8String], [procargs->legacyExecutablePath length]);
156*19c3b8c2SApple OSS Distributions	}
157*19c3b8c2SApple OSS Distributions	printHexDump(procargs->rawBuffer, procargs->rawBufferSize);
158*19c3b8c2SApple OSS Distributions}
159*19c3b8c2SApple OSS Distributions
160*19c3b8c2SApple OSS Distributionsstatic void printHexDump(void* buffer, size_t size) {
161*19c3b8c2SApple OSS Distributions	#define ROW_LENGTH 24
162*19c3b8c2SApple OSS Distributions	T_LOG("Buffer %p, size %zu", buffer, size);
163*19c3b8c2SApple OSS Distributions	for (size_t row = 0; row < size; row += ROW_LENGTH) {
164*19c3b8c2SApple OSS Distributions		NSMutableString *line = [[NSMutableString alloc] initWithCapacity:0];
165*19c3b8c2SApple OSS Distributions		NSMutableString *text = [[NSMutableString alloc] initWithCapacity:0];
166*19c3b8c2SApple OSS Distributions		[line appendFormat:@"    %04zx    ", row];
167*19c3b8c2SApple OSS Distributions		for (size_t col = row; col < row + ROW_LENGTH; col++) {
168*19c3b8c2SApple OSS Distributions			if (col < size) {
169*19c3b8c2SApple OSS Distributions				char c = ((char *)buffer)[col];
170*19c3b8c2SApple OSS Distributions				[line appendFormat:@"%02x ", c];
171*19c3b8c2SApple OSS Distributions				if (isprint(c)) {
172*19c3b8c2SApple OSS Distributions					[text appendFormat:@"%c", c];
173*19c3b8c2SApple OSS Distributions				} else {
174*19c3b8c2SApple OSS Distributions					[text appendString:@"."];
175*19c3b8c2SApple OSS Distributions				}
176*19c3b8c2SApple OSS Distributions			} else {
177*19c3b8c2SApple OSS Distributions				[line appendString:@"   "];
178*19c3b8c2SApple OSS Distributions			}
179*19c3b8c2SApple OSS Distributions		}
180*19c3b8c2SApple OSS Distributions		[line appendFormat:@"  %@", text];
181*19c3b8c2SApple OSS Distributions		T_LOG("%s", [line UTF8String]);
182*19c3b8c2SApple OSS Distributions		[text release];
183*19c3b8c2SApple OSS Distributions		[line release];
184*19c3b8c2SApple OSS Distributions	}
185*19c3b8c2SApple OSS Distributions}
186*19c3b8c2SApple OSS Distributions
187*19c3b8c2SApple OSS Distributionsstatic void deallocProcArgs(procargs_t procargs)
188*19c3b8c2SApple OSS Distributions{
189*19c3b8c2SApple OSS Distributions	[procargs->components release];
190*19c3b8c2SApple OSS Distributions	[procargs->executablePath release];
191*19c3b8c2SApple OSS Distributions	[procargs->legacyExecutablePath release];
192*19c3b8c2SApple OSS Distributions	free(procargs->rawBuffer);
193*19c3b8c2SApple OSS Distributions	free(procargs);
194*19c3b8c2SApple OSS Distributions}
195*19c3b8c2SApple OSS Distributions
196*19c3b8c2SApple OSS DistributionsT_HELPER_DECL(child_helper, "Child process helper")
197*19c3b8c2SApple OSS Distributions{
198*19c3b8c2SApple OSS Distributions	while (true) {
199*19c3b8c2SApple OSS Distributions		wait(NULL);
200*19c3b8c2SApple OSS Distributions	}
201*19c3b8c2SApple OSS Distributions}
202*19c3b8c2SApple OSS Distributions
203*19c3b8c2SApple OSS Distributionsstatic pid_t
204*19c3b8c2SApple OSS Distributionslaunch_child_process(NSArray *args, bool cs_restrict)
205*19c3b8c2SApple OSS Distributions{
206*19c3b8c2SApple OSS Distributions	pid_t pid;
207*19c3b8c2SApple OSS Distributions	char path[PATH_MAX];
208*19c3b8c2SApple OSS Distributions	uint32_t path_size = sizeof(path);
209*19c3b8c2SApple OSS Distributions	uint32_t csopsStatus = 0;
210*19c3b8c2SApple OSS Distributions	const char** dt_args;
211*19c3b8c2SApple OSS Distributions	size_t dt_args_count;
212*19c3b8c2SApple OSS Distributions
213*19c3b8c2SApple OSS Distributions	T_ASSERT_POSIX_SUCCESS(_NSGetExecutablePath(path, &path_size), "get executable path");
214*19c3b8c2SApple OSS Distributions
215*19c3b8c2SApple OSS Distributions	/* We need to add 4 arguments to the beginning and NULL at the end */
216*19c3b8c2SApple OSS Distributions	dt_args_count = [args count] + 5;
217*19c3b8c2SApple OSS Distributions	dt_args = malloc(sizeof(char *) * dt_args_count);
218*19c3b8c2SApple OSS Distributions	dt_args[0] = path;
219*19c3b8c2SApple OSS Distributions	dt_args[1] = "-n";
220*19c3b8c2SApple OSS Distributions	dt_args[2] = "child_helper";
221*19c3b8c2SApple OSS Distributions	dt_args[3] = "--";
222*19c3b8c2SApple OSS Distributions	for (size_t i = 0; i < [args count]; i++) {
223*19c3b8c2SApple OSS Distributions		NSString *arg = [args objectAtIndex:i];
224*19c3b8c2SApple OSS Distributions		dt_args[i + 4] = [arg UTF8String];
225*19c3b8c2SApple OSS Distributions	}
226*19c3b8c2SApple OSS Distributions	dt_args[[args count] + 4] = NULL;
227*19c3b8c2SApple OSS Distributions
228*19c3b8c2SApple OSS Distributions	T_LOG("Launching %s", path);
229*19c3b8c2SApple OSS Distributions	T_LOG("Arguments: ");
230*19c3b8c2SApple OSS Distributions	for (size_t i = 0; i < dt_args_count; i++) {
231*19c3b8c2SApple OSS Distributions		T_LOG("     %s", dt_args[i] ? dt_args[i] : "(null)");
232*19c3b8c2SApple OSS Distributions	}
233*19c3b8c2SApple OSS Distributions	T_ASSERT_POSIX_SUCCESS(dt_launch_tool(&pid, (char **)dt_args, false, NULL, NULL), "launched helper");
234*19c3b8c2SApple OSS Distributions	free(dt_args);
235*19c3b8c2SApple OSS Distributions
236*19c3b8c2SApple OSS Distributions	if (cs_restrict) {
237*19c3b8c2SApple OSS Distributions		csopsStatus |= CS_RESTRICT;
238*19c3b8c2SApple OSS Distributions		T_ASSERT_POSIX_SUCCESS(csops(pid, CS_OPS_SET_STATUS, &csopsStatus, sizeof(csopsStatus)), "set CS_RESTRICT");
239*19c3b8c2SApple OSS Distributions	}
240*19c3b8c2SApple OSS Distributions	return pid;
241*19c3b8c2SApple OSS Distributions}
242*19c3b8c2SApple OSS Distributions
243*19c3b8c2SApple OSS DistributionsT_DECL(test_sysctl_kern_procargs_25397314, "Test kern.procargs and kern.procargs2 sysctls")
244*19c3b8c2SApple OSS Distributions{
245*19c3b8c2SApple OSS Distributions	procargs_t procargs;
246*19c3b8c2SApple OSS Distributions	size_t argsize = sizeof(argmax);
247*19c3b8c2SApple OSS Distributions	NSString *testArgument1 = @"test argument 1";
248*19c3b8c2SApple OSS Distributions	bool containsTestArgument1 = false;
249*19c3b8c2SApple OSS Distributions	NSString *testArgument2 = @"test argument 2";
250*19c3b8c2SApple OSS Distributions	bool containsTestArgument2 = false;
251*19c3b8c2SApple OSS Distributions	NSString *testEnvironmentVariable = @TEST_ENVIRONMENT_VARIABLE;
252*19c3b8c2SApple OSS Distributions	bool containsTestEnvironmentVariable = false;
253*19c3b8c2SApple OSS Distributions	bool containsPathEnvironmentVariable = false;
254*19c3b8c2SApple OSS Distributions	int development = 0;
255*19c3b8c2SApple OSS Distributions	size_t development_size = sizeof(development);
256*19c3b8c2SApple OSS Distributions	uint32_t csopsStatus = 0;
257*19c3b8c2SApple OSS Distributions
258*19c3b8c2SApple OSS Distributions
259*19c3b8c2SApple OSS Distributions	T_ASSERT_POSIX_SUCCESS(sysctlbyname("kern.development", &development, &development_size, NULL, 0), "sysctl kern.development");
260*19c3b8c2SApple OSS Distributions
261*19c3b8c2SApple OSS Distributions	T_ASSERT_POSIX_SUCCESS(sysctlbyname("kern.argmax", &argmax, &argsize, NULL, 0), "sysctl kern.argmax");
262*19c3b8c2SApple OSS Distributions	procargs = getProcArgs(KERN_PROCARGS2, getpid(), argmax);
263*19c3b8c2SApple OSS Distributions	T_ASSERT_NOTNULL(procargs->executablePath, "executable path should be non-null");
264*19c3b8c2SApple OSS Distributions	T_ASSERT_GT([procargs->executablePath length], 0, "executable path should not be empty");
265*19c3b8c2SApple OSS Distributions	printProcArgs(procargs);
266*19c3b8c2SApple OSS Distributions	deallocProcArgs(procargs);
267*19c3b8c2SApple OSS Distributions
268*19c3b8c2SApple OSS Distributions	procargs = getProcArgs(KERN_PROCARGS2, getpid(), 0);
269*19c3b8c2SApple OSS Distributions	T_ASSERT_NOTNULL(procargs->executablePath, "executable path should be non-null");
270*19c3b8c2SApple OSS Distributions	T_ASSERT_GT([procargs->executablePath length], 0, "executable path should not be empty");
271*19c3b8c2SApple OSS Distributions	printProcArgs(procargs);
272*19c3b8c2SApple OSS Distributions	deallocProcArgs(procargs);
273*19c3b8c2SApple OSS Distributions
274*19c3b8c2SApple OSS Distributions	setenv(TEST_ENVIRONMENT_VARIABLE, TEST_ENVIRONMENT_VARIABLE_VALUE, true);
275*19c3b8c2SApple OSS Distributions
276*19c3b8c2SApple OSS Distributions	pid_t child = launch_child_process(@[testArgument1, testArgument2], false);
277*19c3b8c2SApple OSS Distributions	procargs = getProcArgs(KERN_PROCARGS2, child, argmax);
278*19c3b8c2SApple OSS Distributions	T_ASSERT_NOTNULL(procargs->executablePath, "executable path should be non-null");
279*19c3b8c2SApple OSS Distributions	T_ASSERT_GT([procargs->executablePath length], 0, "executable path should not be empty");
280*19c3b8c2SApple OSS Distributions	printProcArgs(procargs);
281*19c3b8c2SApple OSS Distributions
282*19c3b8c2SApple OSS Distributions	for (NSString *component in procargs->components) {
283*19c3b8c2SApple OSS Distributions		if ([component isEqualToString:testArgument1]) {
284*19c3b8c2SApple OSS Distributions			containsTestArgument1 = true;
285*19c3b8c2SApple OSS Distributions		}
286*19c3b8c2SApple OSS Distributions		if ([component isEqualToString:testArgument2]) {
287*19c3b8c2SApple OSS Distributions			containsTestArgument2 = true;
288*19c3b8c2SApple OSS Distributions		}
289*19c3b8c2SApple OSS Distributions		if ([component containsString:testEnvironmentVariable]) {
290*19c3b8c2SApple OSS Distributions			containsTestEnvironmentVariable = true;
291*19c3b8c2SApple OSS Distributions		}
292*19c3b8c2SApple OSS Distributions	}
293*19c3b8c2SApple OSS Distributions	deallocProcArgs(procargs);
294*19c3b8c2SApple OSS Distributions	kill(child, SIGKILL);
295*19c3b8c2SApple OSS Distributions	T_ASSERT_TRUE(containsTestArgument1, "Found test argument 1");
296*19c3b8c2SApple OSS Distributions	T_ASSERT_TRUE(containsTestArgument2, "Found test argument 2");
297*19c3b8c2SApple OSS Distributions	T_ASSERT_TRUE(containsTestEnvironmentVariable, "Found test environment variable");
298*19c3b8c2SApple OSS Distributions
299*19c3b8c2SApple OSS Distributions	if (development) {
300*19c3b8c2SApple OSS Distributions		T_LOG("Skipping test on DEVELOPMENT || DEBUG kernel");
301*19c3b8c2SApple OSS Distributions	} else {
302*19c3b8c2SApple OSS Distributions		containsTestArgument1 = false;
303*19c3b8c2SApple OSS Distributions		containsTestArgument2 = false;
304*19c3b8c2SApple OSS Distributions		containsTestEnvironmentVariable = false;
305*19c3b8c2SApple OSS Distributions
306*19c3b8c2SApple OSS Distributions		child = launch_child_process(@[testArgument1, testArgument2], true);
307*19c3b8c2SApple OSS Distributions		procargs = getProcArgs(KERN_PROCARGS2, child, argmax);
308*19c3b8c2SApple OSS Distributions		T_ASSERT_NOTNULL(procargs->executablePath, "executable path should be non-null");
309*19c3b8c2SApple OSS Distributions		T_ASSERT_GT([procargs->executablePath length], 0, "executable path should not be empty");
310*19c3b8c2SApple OSS Distributions		printProcArgs(procargs);
311*19c3b8c2SApple OSS Distributions		for (NSString *component in procargs->components) {
312*19c3b8c2SApple OSS Distributions			if ([component isEqualToString:testArgument1]) {
313*19c3b8c2SApple OSS Distributions				containsTestArgument1 = true;
314*19c3b8c2SApple OSS Distributions			}
315*19c3b8c2SApple OSS Distributions			if ([component isEqualToString:testArgument2]) {
316*19c3b8c2SApple OSS Distributions				containsTestArgument2 = true;
317*19c3b8c2SApple OSS Distributions			}
318*19c3b8c2SApple OSS Distributions			if ([component containsString:testEnvironmentVariable]) {
319*19c3b8c2SApple OSS Distributions				containsTestEnvironmentVariable = true;
320*19c3b8c2SApple OSS Distributions			}
321*19c3b8c2SApple OSS Distributions		}
322*19c3b8c2SApple OSS Distributions		deallocProcArgs(procargs);
323*19c3b8c2SApple OSS Distributions		kill(child, SIGKILL);
324*19c3b8c2SApple OSS Distributions		T_ASSERT_TRUE(containsTestArgument1, "Found test argument 1");
325*19c3b8c2SApple OSS Distributions		T_ASSERT_TRUE(containsTestArgument2, "Found test argument 2");
326*19c3b8c2SApple OSS Distributions		T_ASSERT_FALSE(containsTestEnvironmentVariable, "No test environment variable");
327*19c3b8c2SApple OSS Distributions
328*19c3b8c2SApple OSS Distributions
329*19c3b8c2SApple OSS Distributions		csopsStatus |= CS_RESTRICT;
330*19c3b8c2SApple OSS Distributions		T_ASSERT_POSIX_SUCCESS(csops(getpid(), CS_OPS_SET_STATUS, &csopsStatus, sizeof(csopsStatus)), "set CS_RESTRICT on self");
331*19c3b8c2SApple OSS Distributions		procargs = getProcArgs(KERN_PROCARGS2, getpid(), argmax);
332*19c3b8c2SApple OSS Distributions		T_ASSERT_NOTNULL(procargs->executablePath, "executable path should be non-null");
333*19c3b8c2SApple OSS Distributions		T_ASSERT_GT([procargs->executablePath length], 0, "executable path should not be empty");
334*19c3b8c2SApple OSS Distributions		printProcArgs(procargs);
335*19c3b8c2SApple OSS Distributions		for (NSString *component in procargs->components) {
336*19c3b8c2SApple OSS Distributions			if ([component containsString:@"PATH"]) {
337*19c3b8c2SApple OSS Distributions				containsPathEnvironmentVariable = true;
338*19c3b8c2SApple OSS Distributions			}
339*19c3b8c2SApple OSS Distributions		}
340*19c3b8c2SApple OSS Distributions		deallocProcArgs(procargs);
341*19c3b8c2SApple OSS Distributions		T_ASSERT_TRUE(containsPathEnvironmentVariable, "Found $PATH environment variable");
342*19c3b8c2SApple OSS Distributions	}
343*19c3b8c2SApple OSS Distributions}
344