xref: /titanic_51/usr/src/cmd/amt/amt.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  * Abstract Machine Test; executes memory access tests to show
31*7c478bd9Sstevel@tonic-gate  * compliance with Common Criteria object reuse and process address
32*7c478bd9Sstevel@tonic-gate  * space separation requirements.
33*7c478bd9Sstevel@tonic-gate  */
34*7c478bd9Sstevel@tonic-gate #include <errno.h>
35*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
36*7c478bd9Sstevel@tonic-gate #include <iso/stdlib_iso.h>
37*7c478bd9Sstevel@tonic-gate #include <libelf.h>
38*7c478bd9Sstevel@tonic-gate #include <libintl.h>
39*7c478bd9Sstevel@tonic-gate #include <locale.h>
40*7c478bd9Sstevel@tonic-gate #include <signal.h>
41*7c478bd9Sstevel@tonic-gate #include <stdio.h>
42*7c478bd9Sstevel@tonic-gate #include <string.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/resource.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
46*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
47*7c478bd9Sstevel@tonic-gate #include <unistd.h>
48*7c478bd9Sstevel@tonic-gate #include <wait.h>
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate #define	NOT_SILENT 0
51*7c478bd9Sstevel@tonic-gate #define	SILENT_MODE 1
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate #define	CHILD_SLEEP_PERIOD 2
54*7c478bd9Sstevel@tonic-gate #define	PARENT_SLEEP_PERIOD 1
55*7c478bd9Sstevel@tonic-gate #define	SIG_EVENT SIGUSR1
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate #define	PASS	   0		/* test passed, no SEGV */
58*7c478bd9Sstevel@tonic-gate #define	FAIL_ZERO  1		/* expected to read zero, didn't */
59*7c478bd9Sstevel@tonic-gate #define	FAIL_SEGV  2		/* expected good read or write, didn't */
60*7c478bd9Sstevel@tonic-gate #define	PASS_SEGV  3		/* expected SEGV, got it */
61*7c478bd9Sstevel@tonic-gate #define	FAIL_ABORT 4		/* test logic error */
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate #define	PH_VALID   0		/* arg for probe_hole -- do valid memory */
64*7c478bd9Sstevel@tonic-gate 				/* access */
65*7c478bd9Sstevel@tonic-gate #define	PH_INVALID 1		/* do illegal memory access */
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate #define	WASTE_PAGES   8		/* a guess at where virgin stack space */
68*7c478bd9Sstevel@tonic-gate 				/* is likely to exist */
69*7c478bd9Sstevel@tonic-gate #define	STACK_SLOP  256		/* a guess at how far below current end */
70*7c478bd9Sstevel@tonic-gate 				/* of stack I'll find unused space */
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
73*7c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"
74*7c478bd9Sstevel@tonic-gate #endif
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate extern int _end;	/* first address after the end of initialized data */
77*7c478bd9Sstevel@tonic-gate 
78*7c478bd9Sstevel@tonic-gate static int  data_boundary_test();
79*7c478bd9Sstevel@tonic-gate static void handler(int);
80*7c478bd9Sstevel@tonic-gate static int  memory_not_shared_after_use();
81*7c478bd9Sstevel@tonic-gate static int  memory_allocation_not_shared();
82*7c478bd9Sstevel@tonic-gate static int  memory_type(const char *);
83*7c478bd9Sstevel@tonic-gate static void print_message(char *);
84*7c478bd9Sstevel@tonic-gate static void probe_data_area(void);
85*7c478bd9Sstevel@tonic-gate static void probe_hole(int);
86*7c478bd9Sstevel@tonic-gate static void probe_stack(void);
87*7c478bd9Sstevel@tonic-gate static void probe_text_area(void);
88*7c478bd9Sstevel@tonic-gate static void segv_action(int, siginfo_t *, void *);
89*7c478bd9Sstevel@tonic-gate static void set_handler(int);
90*7c478bd9Sstevel@tonic-gate static int  test_stack_end_of_hole();
91*7c478bd9Sstevel@tonic-gate static int  text_area_not_writeable();
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate static int done_memory_grab = 0;
94*7c478bd9Sstevel@tonic-gate static int silent;
95*7c478bd9Sstevel@tonic-gate static int handler_exit_code;
96*7c478bd9Sstevel@tonic-gate 
97*7c478bd9Sstevel@tonic-gate /*
98*7c478bd9Sstevel@tonic-gate  * Main Routine
99*7c478bd9Sstevel@tonic-gate  */
100*7c478bd9Sstevel@tonic-gate int
101*7c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
102*7c478bd9Sstevel@tonic-gate {
103*7c478bd9Sstevel@tonic-gate 	int fail_count = 0;
104*7c478bd9Sstevel@tonic-gate 	int status = 0;
105*7c478bd9Sstevel@tonic-gate 	int bitsize;
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate 	/* Internationalization */
108*7c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
109*7c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate 	silent = NOT_SILENT;
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate 	if (argc == 2) {
114*7c478bd9Sstevel@tonic-gate 		/* Pull out argument provided		 */
115*7c478bd9Sstevel@tonic-gate 		/* -s	silent mode, no status or error messages. */
116*7c478bd9Sstevel@tonic-gate 		if (strncmp(argv[1], "-s", 4) == 0)
117*7c478bd9Sstevel@tonic-gate 			silent = SILENT_MODE;
118*7c478bd9Sstevel@tonic-gate 		else {
119*7c478bd9Sstevel@tonic-gate 			/* Wrong argument */
120*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
121*7c478bd9Sstevel@tonic-gate 			    "Wrong argument, USAGE: amt [-s]\n"));
122*7c478bd9Sstevel@tonic-gate 			exit(EXIT_FAILURE);
123*7c478bd9Sstevel@tonic-gate 		}
124*7c478bd9Sstevel@tonic-gate 	} else if (argc != 1) {
125*7c478bd9Sstevel@tonic-gate 		/* Illegal number of arguments. */
126*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
127*7c478bd9Sstevel@tonic-gate 		    "Wrong usage, USAGE: amt [-s]\n"));
128*7c478bd9Sstevel@tonic-gate 		exit(EXIT_FAILURE);
129*7c478bd9Sstevel@tonic-gate 	}
130*7c478bd9Sstevel@tonic-gate 	bitsize = memory_type(argv[0]);
131*7c478bd9Sstevel@tonic-gate 
132*7c478bd9Sstevel@tonic-gate 	if (silent == NOT_SILENT)
133*7c478bd9Sstevel@tonic-gate 		(void) printf(gettext(
134*7c478bd9Sstevel@tonic-gate 		    "\n\nAMT Test Program -- %d bit application\n"
135*7c478bd9Sstevel@tonic-gate 		    "================\n"), bitsize);
136*7c478bd9Sstevel@tonic-gate 	/*
137*7c478bd9Sstevel@tonic-gate 	 * test_stack_end_of_hole must be the first test, or the stack
138*7c478bd9Sstevel@tonic-gate 	 * is of an unknown size.
139*7c478bd9Sstevel@tonic-gate 	 */
140*7c478bd9Sstevel@tonic-gate 	if ((status = test_stack_end_of_hole()) == EXIT_FAILURE) {
141*7c478bd9Sstevel@tonic-gate 		/* Normal fail */
142*7c478bd9Sstevel@tonic-gate 		fail_count++;
143*7c478bd9Sstevel@tonic-gate 		print_message(gettext("TEST 1 FAILED\n"));
144*7c478bd9Sstevel@tonic-gate 	} else if (status == FAIL_ABORT) {
145*7c478bd9Sstevel@tonic-gate 		/* Test logic failure */
146*7c478bd9Sstevel@tonic-gate 		fail_count++;
147*7c478bd9Sstevel@tonic-gate 		print_message(gettext("FAIL: Logic error in test\n"));
148*7c478bd9Sstevel@tonic-gate 	} else if (status == EXIT_SUCCESS)
149*7c478bd9Sstevel@tonic-gate 		print_message(gettext("TEST 1 PASSED\n"));
150*7c478bd9Sstevel@tonic-gate 
151*7c478bd9Sstevel@tonic-gate 	/* Carry out test 2 */
152*7c478bd9Sstevel@tonic-gate 	if (data_boundary_test() != EXIT_SUCCESS) {
153*7c478bd9Sstevel@tonic-gate 		fail_count++;
154*7c478bd9Sstevel@tonic-gate 		print_message(gettext("TEST 2 FAILED\n"));
155*7c478bd9Sstevel@tonic-gate 	} else
156*7c478bd9Sstevel@tonic-gate 		print_message(gettext("TEST 2 PASSED\n"));
157*7c478bd9Sstevel@tonic-gate 
158*7c478bd9Sstevel@tonic-gate 	/* Carry out test 3 */
159*7c478bd9Sstevel@tonic-gate 	if (text_area_not_writeable() != EXIT_SUCCESS) {
160*7c478bd9Sstevel@tonic-gate 		fail_count++;
161*7c478bd9Sstevel@tonic-gate 		print_message(gettext("TEST 3 FAILED\n"));
162*7c478bd9Sstevel@tonic-gate 	} else
163*7c478bd9Sstevel@tonic-gate 		print_message(gettext("TEST 3 PASSED\n"));
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate 	/* Carry out test 4 */
166*7c478bd9Sstevel@tonic-gate 	if (memory_not_shared_after_use() != EXIT_SUCCESS) {
167*7c478bd9Sstevel@tonic-gate 		fail_count++;
168*7c478bd9Sstevel@tonic-gate 		print_message(gettext("TEST 4 FAILED\n"));
169*7c478bd9Sstevel@tonic-gate 	} else
170*7c478bd9Sstevel@tonic-gate 		print_message(gettext("TEST 4 PASSED\n"));
171*7c478bd9Sstevel@tonic-gate 
172*7c478bd9Sstevel@tonic-gate 	/* Carry out test 5 */
173*7c478bd9Sstevel@tonic-gate 	if (memory_allocation_not_shared() != EXIT_SUCCESS) {
174*7c478bd9Sstevel@tonic-gate 		fail_count++;
175*7c478bd9Sstevel@tonic-gate 		print_message(gettext("TEST 5 FAILED\n"));
176*7c478bd9Sstevel@tonic-gate 	} else
177*7c478bd9Sstevel@tonic-gate 		print_message(gettext("TEST 5 PASSED\n"));
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate 	if (silent == NOT_SILENT) {
180*7c478bd9Sstevel@tonic-gate 		if (fail_count > 0)
181*7c478bd9Sstevel@tonic-gate 			(void) printf(gettext("\n %d TESTS FAILED\n\n"),
182*7c478bd9Sstevel@tonic-gate 			    fail_count);
183*7c478bd9Sstevel@tonic-gate 		else
184*7c478bd9Sstevel@tonic-gate 			(void) printf(gettext("\nTESTS SUCCEEDED\n\n"));
185*7c478bd9Sstevel@tonic-gate 	}
186*7c478bd9Sstevel@tonic-gate 	return (fail_count);
187*7c478bd9Sstevel@tonic-gate }
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate /*
190*7c478bd9Sstevel@tonic-gate  * Test the data boundaries. First test inside the data area at the boundary
191*7c478bd9Sstevel@tonic-gate  * of the "hole" area. Second test inside the data area at the text area
192*7c478bd9Sstevel@tonic-gate  * boundary. Both should pass.
193*7c478bd9Sstevel@tonic-gate  */
194*7c478bd9Sstevel@tonic-gate static int
195*7c478bd9Sstevel@tonic-gate data_boundary_test()
196*7c478bd9Sstevel@tonic-gate {
197*7c478bd9Sstevel@tonic-gate 	int exit_status = EXIT_SUCCESS;
198*7c478bd9Sstevel@tonic-gate 	pid_t pid;
199*7c478bd9Sstevel@tonic-gate 	int status;
200*7c478bd9Sstevel@tonic-gate 
201*7c478bd9Sstevel@tonic-gate 	print_message(gettext("\n\nTest 2- Data Side Boundary Test.\n"));
202*7c478bd9Sstevel@tonic-gate 
203*7c478bd9Sstevel@tonic-gate 	if ((pid = fork()) == -1) {
204*7c478bd9Sstevel@tonic-gate 		print_message(gettext("Fork failed\n"));
205*7c478bd9Sstevel@tonic-gate 		return (EXIT_FAILURE);
206*7c478bd9Sstevel@tonic-gate 	} else if (pid == 0) { /* Am I my child? */
207*7c478bd9Sstevel@tonic-gate 		set_handler(SIGSEGV);
208*7c478bd9Sstevel@tonic-gate 
209*7c478bd9Sstevel@tonic-gate 		/* probe_data_area() does exit() */
210*7c478bd9Sstevel@tonic-gate 		probe_data_area();
211*7c478bd9Sstevel@tonic-gate 	}
212*7c478bd9Sstevel@tonic-gate 	/* still parent */
213*7c478bd9Sstevel@tonic-gate 	(void) wait(&status);
214*7c478bd9Sstevel@tonic-gate 	status = WEXITSTATUS(status);
215*7c478bd9Sstevel@tonic-gate 
216*7c478bd9Sstevel@tonic-gate 	if (status == PASS)
217*7c478bd9Sstevel@tonic-gate 		print_message(gettext(
218*7c478bd9Sstevel@tonic-gate 		    "PASS: Successful read/write in data area.\n"));
219*7c478bd9Sstevel@tonic-gate 	else if (status == FAIL_SEGV) {
220*7c478bd9Sstevel@tonic-gate 		print_message(gettext(
221*7c478bd9Sstevel@tonic-gate 		    "FAIL: Caught a segmentation fault while "
222*7c478bd9Sstevel@tonic-gate 		    "attempting to write to the data area.\n"));
223*7c478bd9Sstevel@tonic-gate 		exit_status = EXIT_FAILURE;
224*7c478bd9Sstevel@tonic-gate 	} else {
225*7c478bd9Sstevel@tonic-gate 		(void) printf(gettext("Test program failure: %d\n"),
226*7c478bd9Sstevel@tonic-gate 		    status);
227*7c478bd9Sstevel@tonic-gate 		exit_status = EXIT_FAILURE;
228*7c478bd9Sstevel@tonic-gate 	}
229*7c478bd9Sstevel@tonic-gate 	return (exit_status);
230*7c478bd9Sstevel@tonic-gate }
231*7c478bd9Sstevel@tonic-gate 
232*7c478bd9Sstevel@tonic-gate static void
233*7c478bd9Sstevel@tonic-gate probe_data_area()
234*7c478bd9Sstevel@tonic-gate {
235*7c478bd9Sstevel@tonic-gate 	int *p;
236*7c478bd9Sstevel@tonic-gate 	/* LINTED */
237*7c478bd9Sstevel@tonic-gate 	volatile int p1;
238*7c478bd9Sstevel@tonic-gate 	void *address;
239*7c478bd9Sstevel@tonic-gate 
240*7c478bd9Sstevel@tonic-gate 	/* set handler status */
241*7c478bd9Sstevel@tonic-gate 	handler_exit_code = FAIL_SEGV;
242*7c478bd9Sstevel@tonic-gate 
243*7c478bd9Sstevel@tonic-gate 	/*
244*7c478bd9Sstevel@tonic-gate 	 * Get an address in the data area, near to the "hole".
245*7c478bd9Sstevel@tonic-gate 	 * sbrk returns prior address value; rather than calculating
246*7c478bd9Sstevel@tonic-gate 	 * the sbrk result, sbrk is called twice, so address points
247*7c478bd9Sstevel@tonic-gate 	 * to the new end of data
248*7c478bd9Sstevel@tonic-gate 	 */
249*7c478bd9Sstevel@tonic-gate 	(void) sbrk(PAGESIZE);
250*7c478bd9Sstevel@tonic-gate 	address = sbrk(0);
251*7c478bd9Sstevel@tonic-gate 	/*
252*7c478bd9Sstevel@tonic-gate 	 * Get to the inside edge of a page boundary
253*7c478bd9Sstevel@tonic-gate 	 * two integer words short of a new page
254*7c478bd9Sstevel@tonic-gate 	 */
255*7c478bd9Sstevel@tonic-gate 	p = ((int *)P2ROUNDUP((uintptr_t)address, PAGESIZE)) - 2;
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate 	/* Try writing to it, shouldn't cause a segmentation fault. */
258*7c478bd9Sstevel@tonic-gate 	*p = 9999;
259*7c478bd9Sstevel@tonic-gate 
260*7c478bd9Sstevel@tonic-gate 	/* Should be able to read back with no problems. */
261*7c478bd9Sstevel@tonic-gate 	p1 = *p;
262*7c478bd9Sstevel@tonic-gate 
263*7c478bd9Sstevel@tonic-gate 	/*
264*7c478bd9Sstevel@tonic-gate 	 * Get an address near the text area boundary, but in the data
265*7c478bd9Sstevel@tonic-gate 	 * area.  _etext rounded up a page isn't correct since the
266*7c478bd9Sstevel@tonic-gate 	 * initialized data area isn't writeable.
267*7c478bd9Sstevel@tonic-gate 	 *
268*7c478bd9Sstevel@tonic-gate 	 * Future versions should consider handling initialized data
269*7c478bd9Sstevel@tonic-gate 	 * separately -- writing to initialized data should generate
270*7c478bd9Sstevel@tonic-gate 	 * a fault.
271*7c478bd9Sstevel@tonic-gate 	 */
272*7c478bd9Sstevel@tonic-gate 	p = &_end;
273*7c478bd9Sstevel@tonic-gate 
274*7c478bd9Sstevel@tonic-gate 	/* Try writing to it, should succeed. */
275*7c478bd9Sstevel@tonic-gate 	*p = 9898;
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate 	/* Should be able to read back with no problems. */
278*7c478bd9Sstevel@tonic-gate 	p1 = *p;
279*7c478bd9Sstevel@tonic-gate 
280*7c478bd9Sstevel@tonic-gate 	exit(EXIT_SUCCESS);
281*7c478bd9Sstevel@tonic-gate }
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate /*
284*7c478bd9Sstevel@tonic-gate  * Test that we cannot write to the text area. An attempt to write to
285*7c478bd9Sstevel@tonic-gate  * the text area will result in a segmentation fault. So if we catch it,
286*7c478bd9Sstevel@tonic-gate  * test has succeed, else it has failed.
287*7c478bd9Sstevel@tonic-gate  */
288*7c478bd9Sstevel@tonic-gate static int
289*7c478bd9Sstevel@tonic-gate text_area_not_writeable()
290*7c478bd9Sstevel@tonic-gate {
291*7c478bd9Sstevel@tonic-gate 	int exit_status = EXIT_SUCCESS;
292*7c478bd9Sstevel@tonic-gate 	pid_t pid;
293*7c478bd9Sstevel@tonic-gate 	int status;
294*7c478bd9Sstevel@tonic-gate 
295*7c478bd9Sstevel@tonic-gate 	print_message(gettext(
296*7c478bd9Sstevel@tonic-gate 	    "\n\nTest 3- Text Area Not Writeable\n"
297*7c478bd9Sstevel@tonic-gate 	    "Verify that a write to the text space does not cause "
298*7c478bd9Sstevel@tonic-gate 	    "a write to the executable\n"
299*7c478bd9Sstevel@tonic-gate 	    "file from which it came, or to another process which "
300*7c478bd9Sstevel@tonic-gate 	    "shares that text.\n"));
301*7c478bd9Sstevel@tonic-gate 
302*7c478bd9Sstevel@tonic-gate 	if ((pid = fork()) == -1) {
303*7c478bd9Sstevel@tonic-gate 		print_message(gettext("Fork failed\n"));
304*7c478bd9Sstevel@tonic-gate 		return (EXIT_FAILURE);
305*7c478bd9Sstevel@tonic-gate 	} else if (pid == 0) { /* Am I my child? */
306*7c478bd9Sstevel@tonic-gate 		set_handler(SIGSEGV);
307*7c478bd9Sstevel@tonic-gate 
308*7c478bd9Sstevel@tonic-gate 		/* probe_text_area() does exit() */
309*7c478bd9Sstevel@tonic-gate 		probe_text_area();
310*7c478bd9Sstevel@tonic-gate 	}
311*7c478bd9Sstevel@tonic-gate 	/* still parent */
312*7c478bd9Sstevel@tonic-gate 	(void) wait(&status);
313*7c478bd9Sstevel@tonic-gate 	status = WEXITSTATUS(status);
314*7c478bd9Sstevel@tonic-gate 
315*7c478bd9Sstevel@tonic-gate 	if (status == PASS) {
316*7c478bd9Sstevel@tonic-gate 		print_message(gettext(
317*7c478bd9Sstevel@tonic-gate 		    "FAIL: We did not cause a segmentation fault.\n"));
318*7c478bd9Sstevel@tonic-gate 		exit_status = EXIT_FAILURE;
319*7c478bd9Sstevel@tonic-gate 	} else if (status == FAIL_SEGV) {
320*7c478bd9Sstevel@tonic-gate 		print_message(gettext(
321*7c478bd9Sstevel@tonic-gate 		    "PASS: Caught the segmentation fault, "
322*7c478bd9Sstevel@tonic-gate 		    "meaning we can't write to text area.\n"));
323*7c478bd9Sstevel@tonic-gate 	} else {
324*7c478bd9Sstevel@tonic-gate 		(void) printf(gettext(
325*7c478bd9Sstevel@tonic-gate 		    "Test program failure: %d\n"), status);
326*7c478bd9Sstevel@tonic-gate 		exit_status = EXIT_FAILURE;
327*7c478bd9Sstevel@tonic-gate 	}
328*7c478bd9Sstevel@tonic-gate 	return (exit_status);
329*7c478bd9Sstevel@tonic-gate }
330*7c478bd9Sstevel@tonic-gate 
331*7c478bd9Sstevel@tonic-gate /*
332*7c478bd9Sstevel@tonic-gate  * write to text area, trigger a SEGV
333*7c478bd9Sstevel@tonic-gate  */
334*7c478bd9Sstevel@tonic-gate static void
335*7c478bd9Sstevel@tonic-gate probe_text_area()
336*7c478bd9Sstevel@tonic-gate {
337*7c478bd9Sstevel@tonic-gate 	handler_exit_code = FAIL_SEGV;
338*7c478bd9Sstevel@tonic-gate 	*(caddr_t)probe_text_area = 0xff;
339*7c478bd9Sstevel@tonic-gate 	exit(EXIT_FAILURE);
340*7c478bd9Sstevel@tonic-gate }
341*7c478bd9Sstevel@tonic-gate 
342*7c478bd9Sstevel@tonic-gate /*
343*7c478bd9Sstevel@tonic-gate  * Test that when we set some values and fork a process, when the child
344*7c478bd9Sstevel@tonic-gate  * writes to these inherited values, the parents copies are not changed.
345*7c478bd9Sstevel@tonic-gate  */
346*7c478bd9Sstevel@tonic-gate static int
347*7c478bd9Sstevel@tonic-gate memory_not_shared_after_use()
348*7c478bd9Sstevel@tonic-gate {
349*7c478bd9Sstevel@tonic-gate 	pid_t pid;
350*7c478bd9Sstevel@tonic-gate 	int x = 1000;
351*7c478bd9Sstevel@tonic-gate 	int exit_status = EXIT_SUCCESS;
352*7c478bd9Sstevel@tonic-gate 
353*7c478bd9Sstevel@tonic-gate 	print_message(gettext("\n\nTest 4- Memory Not Shared After Write\n"
354*7c478bd9Sstevel@tonic-gate 	    "Verify that anonymous memory initially shared by two "
355*7c478bd9Sstevel@tonic-gate 	    "processes (e.g. after a\n"
356*7c478bd9Sstevel@tonic-gate 	    "fork) is not shared after either process writes "
357*7c478bd9Sstevel@tonic-gate 	    "to it.\n"));
358*7c478bd9Sstevel@tonic-gate 
359*7c478bd9Sstevel@tonic-gate 	if ((pid = fork()) == -1) {
360*7c478bd9Sstevel@tonic-gate 		print_message(gettext("Fork failed\n"));
361*7c478bd9Sstevel@tonic-gate 		return (EXIT_FAILURE);
362*7c478bd9Sstevel@tonic-gate 	} else if (pid == 0) { /* I am the child. */
363*7c478bd9Sstevel@tonic-gate 		/*
364*7c478bd9Sstevel@tonic-gate 		 * Change child value; this should not change
365*7c478bd9Sstevel@tonic-gate 		 * parent value.
366*7c478bd9Sstevel@tonic-gate 		 */
367*7c478bd9Sstevel@tonic-gate 		x = 2000;
368*7c478bd9Sstevel@tonic-gate 
369*7c478bd9Sstevel@tonic-gate 		/* Wait for parent to test value */
370*7c478bd9Sstevel@tonic-gate 		(void) sleep(CHILD_SLEEP_PERIOD);
371*7c478bd9Sstevel@tonic-gate 
372*7c478bd9Sstevel@tonic-gate 		exit(EXIT_SUCCESS);
373*7c478bd9Sstevel@tonic-gate 	}
374*7c478bd9Sstevel@tonic-gate 	/* Wait for child to do its stuff. */
375*7c478bd9Sstevel@tonic-gate 	(void) sleep(PARENT_SLEEP_PERIOD);
376*7c478bd9Sstevel@tonic-gate 
377*7c478bd9Sstevel@tonic-gate 	if (x == 1000)
378*7c478bd9Sstevel@tonic-gate 		exit_status = EXIT_SUCCESS;
379*7c478bd9Sstevel@tonic-gate 	else
380*7c478bd9Sstevel@tonic-gate 		exit_status = EXIT_FAILURE;
381*7c478bd9Sstevel@tonic-gate 
382*7c478bd9Sstevel@tonic-gate 	return (exit_status);
383*7c478bd9Sstevel@tonic-gate }
384*7c478bd9Sstevel@tonic-gate 
385*7c478bd9Sstevel@tonic-gate /*
386*7c478bd9Sstevel@tonic-gate  * If we fork a process and then allocate some memory in that process,
387*7c478bd9Sstevel@tonic-gate  * we should not see any memory changes in the parent.
388*7c478bd9Sstevel@tonic-gate  */
389*7c478bd9Sstevel@tonic-gate static int
390*7c478bd9Sstevel@tonic-gate memory_allocation_not_shared()
391*7c478bd9Sstevel@tonic-gate {
392*7c478bd9Sstevel@tonic-gate 	pid_t pid;
393*7c478bd9Sstevel@tonic-gate 	pid_t parent_pid;
394*7c478bd9Sstevel@tonic-gate 	int exit_status = 0;
395*7c478bd9Sstevel@tonic-gate 	caddr_t address;
396*7c478bd9Sstevel@tonic-gate 	caddr_t hole_start;
397*7c478bd9Sstevel@tonic-gate 	caddr_t hole_after;
398*7c478bd9Sstevel@tonic-gate 	void (*old_handler) ();
399*7c478bd9Sstevel@tonic-gate 
400*7c478bd9Sstevel@tonic-gate 	print_message(gettext(
401*7c478bd9Sstevel@tonic-gate 	    "\n\nTest 5- Memory Allocation is Not Shared\n"
402*7c478bd9Sstevel@tonic-gate 	    "Verify that newly allocated memory in one of two "
403*7c478bd9Sstevel@tonic-gate 	    "processes created by forking\n"
404*7c478bd9Sstevel@tonic-gate 	    "does not result in newly allocated memory in the other.\n"));
405*7c478bd9Sstevel@tonic-gate 
406*7c478bd9Sstevel@tonic-gate 	/* Save Size of data area and 1st block address of "hole" */
407*7c478bd9Sstevel@tonic-gate 	hole_start = (caddr_t)sbrk(0);
408*7c478bd9Sstevel@tonic-gate 
409*7c478bd9Sstevel@tonic-gate 	if (silent == NOT_SILENT)
410*7c478bd9Sstevel@tonic-gate 		(void) printf(gettext(
411*7c478bd9Sstevel@tonic-gate 		    "Parent address of hole before child change: %08X\n"),
412*7c478bd9Sstevel@tonic-gate 		    hole_start);
413*7c478bd9Sstevel@tonic-gate 
414*7c478bd9Sstevel@tonic-gate 	/* Set handler for signal SIG_EVENT (define at start) */
415*7c478bd9Sstevel@tonic-gate 	old_handler = signal(SIG_EVENT, &handler);
416*7c478bd9Sstevel@tonic-gate 	if (old_handler == SIG_ERR) {
417*7c478bd9Sstevel@tonic-gate 		print_message(gettext(
418*7c478bd9Sstevel@tonic-gate 		    "Can't establish signal handler, test failed\n"));
419*7c478bd9Sstevel@tonic-gate 		return (EXIT_FAILURE);
420*7c478bd9Sstevel@tonic-gate 	}
421*7c478bd9Sstevel@tonic-gate 
422*7c478bd9Sstevel@tonic-gate 	if ((pid = fork()) == -1) {
423*7c478bd9Sstevel@tonic-gate 		print_message(gettext("Fork failed\n"));
424*7c478bd9Sstevel@tonic-gate 		return (EXIT_FAILURE);
425*7c478bd9Sstevel@tonic-gate 	} else if (pid == 0) { /* We are the child. */
426*7c478bd9Sstevel@tonic-gate 		address = sbrk(0);
427*7c478bd9Sstevel@tonic-gate 		if (silent == NOT_SILENT)
428*7c478bd9Sstevel@tonic-gate 			(void) printf(gettext(
429*7c478bd9Sstevel@tonic-gate 			    "Child end of hole before change:  %08X\n"),
430*7c478bd9Sstevel@tonic-gate 			    address);
431*7c478bd9Sstevel@tonic-gate 
432*7c478bd9Sstevel@tonic-gate 		if (brk((address+PAGESIZE)) != 0) {
433*7c478bd9Sstevel@tonic-gate 			print_message(gettext(
434*7c478bd9Sstevel@tonic-gate 			    "Can't change start of hole address.\n"));
435*7c478bd9Sstevel@tonic-gate 			exit(EXIT_FAILURE);
436*7c478bd9Sstevel@tonic-gate 		}
437*7c478bd9Sstevel@tonic-gate 
438*7c478bd9Sstevel@tonic-gate 		address = sbrk(0);
439*7c478bd9Sstevel@tonic-gate 		if (silent == NOT_SILENT)
440*7c478bd9Sstevel@tonic-gate 			(void) printf(gettext(
441*7c478bd9Sstevel@tonic-gate 			    "Child end of hole after change: %08X\n"),
442*7c478bd9Sstevel@tonic-gate 			    address);
443*7c478bd9Sstevel@tonic-gate 
444*7c478bd9Sstevel@tonic-gate 		/* Tell the parent we're done. */
445*7c478bd9Sstevel@tonic-gate 		parent_pid = getppid();
446*7c478bd9Sstevel@tonic-gate 		if (sigsend(P_PID, parent_pid, SIG_EVENT) != 0) {
447*7c478bd9Sstevel@tonic-gate 			print_message(gettext("Can't send signal to parent, "
448*7c478bd9Sstevel@tonic-gate 			    "test failed\n"));
449*7c478bd9Sstevel@tonic-gate 			exit(EXIT_FAILURE);
450*7c478bd9Sstevel@tonic-gate 		}
451*7c478bd9Sstevel@tonic-gate 
452*7c478bd9Sstevel@tonic-gate 		/* Sleep before exiting to allow parent to finish processing. */
453*7c478bd9Sstevel@tonic-gate 		(void) sleep(CHILD_SLEEP_PERIOD);
454*7c478bd9Sstevel@tonic-gate 		exit(EXIT_SUCCESS);
455*7c478bd9Sstevel@tonic-gate 	}
456*7c478bd9Sstevel@tonic-gate 	/* Wait for child to do its work. */
457*7c478bd9Sstevel@tonic-gate 	(void) sleep(PARENT_SLEEP_PERIOD);
458*7c478bd9Sstevel@tonic-gate 
459*7c478bd9Sstevel@tonic-gate 	if (done_memory_grab != 1) {
460*7c478bd9Sstevel@tonic-gate 		print_message(gettext(
461*7c478bd9Sstevel@tonic-gate 		    "Child failed to do memory alterations, "
462*7c478bd9Sstevel@tonic-gate 		    "exiting\n"));
463*7c478bd9Sstevel@tonic-gate 		return (EXIT_FAILURE);
464*7c478bd9Sstevel@tonic-gate 	}
465*7c478bd9Sstevel@tonic-gate 
466*7c478bd9Sstevel@tonic-gate 	hole_after = sbrk(0);
467*7c478bd9Sstevel@tonic-gate 	if (silent == NOT_SILENT)
468*7c478bd9Sstevel@tonic-gate 		(void) printf(gettext(
469*7c478bd9Sstevel@tonic-gate 		    "Parent address of hole after child change: "
470*7c478bd9Sstevel@tonic-gate 		    "%08X\n"), hole_after);
471*7c478bd9Sstevel@tonic-gate 
472*7c478bd9Sstevel@tonic-gate 	/* Test size of hole and data region. */
473*7c478bd9Sstevel@tonic-gate 	if (hole_start == hole_after)
474*7c478bd9Sstevel@tonic-gate 		print_message(gettext(
475*7c478bd9Sstevel@tonic-gate 		    "PASS: Hole is same size in parent.\n"));
476*7c478bd9Sstevel@tonic-gate 	else {
477*7c478bd9Sstevel@tonic-gate 		print_message(gettext(
478*7c478bd9Sstevel@tonic-gate 		    "FAIL: Hole is a different size.\n"));
479*7c478bd9Sstevel@tonic-gate 		exit_status = EXIT_FAILURE;
480*7c478bd9Sstevel@tonic-gate 	}
481*7c478bd9Sstevel@tonic-gate 
482*7c478bd9Sstevel@tonic-gate 	/* Wait for child to finish. */
483*7c478bd9Sstevel@tonic-gate 	(void) wait(0);
484*7c478bd9Sstevel@tonic-gate 
485*7c478bd9Sstevel@tonic-gate 	if (signal(SIG_EVENT, old_handler) == SIG_ERR) {
486*7c478bd9Sstevel@tonic-gate 		print_message(gettext("Couldn't put back old signal handler, "
487*7c478bd9Sstevel@tonic-gate 		    "test failed.\n"));
488*7c478bd9Sstevel@tonic-gate 		return (EXIT_FAILURE);
489*7c478bd9Sstevel@tonic-gate 	}
490*7c478bd9Sstevel@tonic-gate 	return (exit_status);
491*7c478bd9Sstevel@tonic-gate }
492*7c478bd9Sstevel@tonic-gate 
493*7c478bd9Sstevel@tonic-gate static void
494*7c478bd9Sstevel@tonic-gate print_message(char *message)
495*7c478bd9Sstevel@tonic-gate {
496*7c478bd9Sstevel@tonic-gate 	if (silent == NOT_SILENT)
497*7c478bd9Sstevel@tonic-gate 		(void) printf("%s", message);
498*7c478bd9Sstevel@tonic-gate }
499*7c478bd9Sstevel@tonic-gate 
500*7c478bd9Sstevel@tonic-gate static int
501*7c478bd9Sstevel@tonic-gate test_stack_end_of_hole()
502*7c478bd9Sstevel@tonic-gate {
503*7c478bd9Sstevel@tonic-gate 	pid_t pid;
504*7c478bd9Sstevel@tonic-gate 	int status;
505*7c478bd9Sstevel@tonic-gate 	int exit_status = EXIT_SUCCESS;
506*7c478bd9Sstevel@tonic-gate 
507*7c478bd9Sstevel@tonic-gate 	print_message(gettext("\n\nTest 1- stack Side Boundary Test\n"));
508*7c478bd9Sstevel@tonic-gate 
509*7c478bd9Sstevel@tonic-gate 	/* sub test 1:  the space the stack grows into is zero */
510*7c478bd9Sstevel@tonic-gate 
511*7c478bd9Sstevel@tonic-gate 	if ((pid = fork()) == -1) {
512*7c478bd9Sstevel@tonic-gate 		print_message(gettext("Fork failed\n"));
513*7c478bd9Sstevel@tonic-gate 		return (EXIT_FAILURE);
514*7c478bd9Sstevel@tonic-gate 	} else if (pid == 0) { /* Am I my child? */
515*7c478bd9Sstevel@tonic-gate 		set_handler(SIGSEGV);
516*7c478bd9Sstevel@tonic-gate 
517*7c478bd9Sstevel@tonic-gate 		/* probe_stack() does exit */
518*7c478bd9Sstevel@tonic-gate 		probe_stack();
519*7c478bd9Sstevel@tonic-gate 	}
520*7c478bd9Sstevel@tonic-gate 	/* still parent */
521*7c478bd9Sstevel@tonic-gate 	(void) wait(&status);
522*7c478bd9Sstevel@tonic-gate 	status = WEXITSTATUS(status);
523*7c478bd9Sstevel@tonic-gate 
524*7c478bd9Sstevel@tonic-gate 	if (status == FAIL_ZERO) {
525*7c478bd9Sstevel@tonic-gate 		print_message(gettext("Fail with non-zero read.\n"));
526*7c478bd9Sstevel@tonic-gate 		exit_status = EXIT_FAILURE;
527*7c478bd9Sstevel@tonic-gate 	} else if (status != PASS) {
528*7c478bd9Sstevel@tonic-gate 		print_message(gettext("Test program failure\n"));
529*7c478bd9Sstevel@tonic-gate 		exit_status = EXIT_FAILURE;
530*7c478bd9Sstevel@tonic-gate 	}
531*7c478bd9Sstevel@tonic-gate 	/* sub test 2:  the space in hole is not readable */
532*7c478bd9Sstevel@tonic-gate 
533*7c478bd9Sstevel@tonic-gate 	if ((pid = fork()) == -1) {
534*7c478bd9Sstevel@tonic-gate 		print_message(gettext("Fork failed\n"));
535*7c478bd9Sstevel@tonic-gate 		return (EXIT_FAILURE);
536*7c478bd9Sstevel@tonic-gate 	} else if (pid == 0) { /* Am I my child? */
537*7c478bd9Sstevel@tonic-gate 		set_handler(SIGSEGV);
538*7c478bd9Sstevel@tonic-gate 
539*7c478bd9Sstevel@tonic-gate 		/* probe_hole does exit */
540*7c478bd9Sstevel@tonic-gate 		probe_hole(PH_INVALID);
541*7c478bd9Sstevel@tonic-gate 	}
542*7c478bd9Sstevel@tonic-gate 	/* still parent */
543*7c478bd9Sstevel@tonic-gate 	(void) wait(&status);
544*7c478bd9Sstevel@tonic-gate 	status = WEXITSTATUS(status);
545*7c478bd9Sstevel@tonic-gate 
546*7c478bd9Sstevel@tonic-gate 	if (status == FAIL_SEGV) {
547*7c478bd9Sstevel@tonic-gate 		print_message(
548*7c478bd9Sstevel@tonic-gate 		    gettext("Fail (SEGV expected, not received).\n"));
549*7c478bd9Sstevel@tonic-gate 		exit_status = EXIT_FAILURE;
550*7c478bd9Sstevel@tonic-gate 	} else if (status != PASS_SEGV) {
551*7c478bd9Sstevel@tonic-gate 		print_message(gettext("Test program failure.\n"));
552*7c478bd9Sstevel@tonic-gate 		exit_status = EXIT_FAILURE;
553*7c478bd9Sstevel@tonic-gate 	}
554*7c478bd9Sstevel@tonic-gate 
555*7c478bd9Sstevel@tonic-gate 	/* sub test 3:  the space in new page below hole is zero */
556*7c478bd9Sstevel@tonic-gate 
557*7c478bd9Sstevel@tonic-gate 	if ((pid = fork()) == -1) {
558*7c478bd9Sstevel@tonic-gate 		print_message(gettext("Fork failed\n"));
559*7c478bd9Sstevel@tonic-gate 		return (EXIT_FAILURE);
560*7c478bd9Sstevel@tonic-gate 	} else if (pid == 0) { /* Am I my child? */
561*7c478bd9Sstevel@tonic-gate 		set_handler(SIGSEGV);
562*7c478bd9Sstevel@tonic-gate 
563*7c478bd9Sstevel@tonic-gate 		/* probe_hole does exit */
564*7c478bd9Sstevel@tonic-gate 		probe_hole(PH_VALID);
565*7c478bd9Sstevel@tonic-gate 	}
566*7c478bd9Sstevel@tonic-gate 	/* still parent */
567*7c478bd9Sstevel@tonic-gate 	(void) wait(&status);
568*7c478bd9Sstevel@tonic-gate 	status = WEXITSTATUS(status);
569*7c478bd9Sstevel@tonic-gate 
570*7c478bd9Sstevel@tonic-gate 	if (status == FAIL_SEGV) {
571*7c478bd9Sstevel@tonic-gate 		print_message(gettext("Fail (got SEGV).\n"));
572*7c478bd9Sstevel@tonic-gate 		exit_status = EXIT_FAILURE;
573*7c478bd9Sstevel@tonic-gate 	} else if (status != PASS) {
574*7c478bd9Sstevel@tonic-gate 		print_message(gettext("Test program failure.\n"));
575*7c478bd9Sstevel@tonic-gate 		exit_status = EXIT_FAILURE;
576*7c478bd9Sstevel@tonic-gate 	}
577*7c478bd9Sstevel@tonic-gate 	return (exit_status);
578*7c478bd9Sstevel@tonic-gate }
579*7c478bd9Sstevel@tonic-gate 
580*7c478bd9Sstevel@tonic-gate 
581*7c478bd9Sstevel@tonic-gate /*
582*7c478bd9Sstevel@tonic-gate  * set_handler
583*7c478bd9Sstevel@tonic-gate  */
584*7c478bd9Sstevel@tonic-gate static void
585*7c478bd9Sstevel@tonic-gate set_handler(int sig)
586*7c478bd9Sstevel@tonic-gate {
587*7c478bd9Sstevel@tonic-gate 	struct sigaction act;
588*7c478bd9Sstevel@tonic-gate 
589*7c478bd9Sstevel@tonic-gate 	act.sa_handler = NULL;
590*7c478bd9Sstevel@tonic-gate 	act.sa_flags = SA_SIGINFO;
591*7c478bd9Sstevel@tonic-gate 	act.sa_sigaction = segv_action;
592*7c478bd9Sstevel@tonic-gate 	(void) sigemptyset(&(act.sa_mask));
593*7c478bd9Sstevel@tonic-gate 
594*7c478bd9Sstevel@tonic-gate 	if (sigaction(sig, &act, NULL) < 0) {
595*7c478bd9Sstevel@tonic-gate 		if (silent == NOT_SILENT) {
596*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
597*7c478bd9Sstevel@tonic-gate 			    "sigaction() returned error: %s\n"),
598*7c478bd9Sstevel@tonic-gate 			    strerror(errno));
599*7c478bd9Sstevel@tonic-gate 		}
600*7c478bd9Sstevel@tonic-gate 		exit(EXIT_FAILURE);
601*7c478bd9Sstevel@tonic-gate 	}
602*7c478bd9Sstevel@tonic-gate }
603*7c478bd9Sstevel@tonic-gate 
604*7c478bd9Sstevel@tonic-gate 
605*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
606*7c478bd9Sstevel@tonic-gate static void
607*7c478bd9Sstevel@tonic-gate segv_action(int which_sig, siginfo_t *t1, void *t2)
608*7c478bd9Sstevel@tonic-gate {
609*7c478bd9Sstevel@tonic-gate 	exit(handler_exit_code);
610*7c478bd9Sstevel@tonic-gate }
611*7c478bd9Sstevel@tonic-gate 
612*7c478bd9Sstevel@tonic-gate /*
613*7c478bd9Sstevel@tonic-gate  * probe_stack
614*7c478bd9Sstevel@tonic-gate  *
615*7c478bd9Sstevel@tonic-gate  * Warning -- if you do a printf or fprintf prior to the actual
616*7c478bd9Sstevel@tonic-gate  * reading from the stack, you've changed the stack to an unknown
617*7c478bd9Sstevel@tonic-gate  * state.  (stack memory isn't free'd automatically and this function
618*7c478bd9Sstevel@tonic-gate  * needs to touch virgin stack space.)
619*7c478bd9Sstevel@tonic-gate  */
620*7c478bd9Sstevel@tonic-gate static void
621*7c478bd9Sstevel@tonic-gate probe_stack(void)
622*7c478bd9Sstevel@tonic-gate {
623*7c478bd9Sstevel@tonic-gate 	unsigned char *end;	/* end of stack */
624*7c478bd9Sstevel@tonic-gate 	unsigned char probe;
625*7c478bd9Sstevel@tonic-gate 	long i;
626*7c478bd9Sstevel@tonic-gate 	int j;
627*7c478bd9Sstevel@tonic-gate 	unsigned char last_fail, *last_fail_address;
628*7c478bd9Sstevel@tonic-gate 	unsigned char mark = 0xAA;	/* roughly the end of stack */
629*7c478bd9Sstevel@tonic-gate 	handler_exit_code = FAIL_SEGV;
630*7c478bd9Sstevel@tonic-gate 
631*7c478bd9Sstevel@tonic-gate 	end = &mark;
632*7c478bd9Sstevel@tonic-gate 	/* stack growth is negative */
633*7c478bd9Sstevel@tonic-gate 	end -= (WASTE_PAGES * PAGESIZE) + STACK_SLOP;
634*7c478bd9Sstevel@tonic-gate 
635*7c478bd9Sstevel@tonic-gate 	for (i = 0, j = 0; i < PAGESIZE; i++) {
636*7c478bd9Sstevel@tonic-gate 		if ((probe = *end) != 0) {
637*7c478bd9Sstevel@tonic-gate 			j++;
638*7c478bd9Sstevel@tonic-gate 			last_fail = probe;
639*7c478bd9Sstevel@tonic-gate 			last_fail_address = end;
640*7c478bd9Sstevel@tonic-gate 		}
641*7c478bd9Sstevel@tonic-gate 		end--;
642*7c478bd9Sstevel@tonic-gate 	}
643*7c478bd9Sstevel@tonic-gate 
644*7c478bd9Sstevel@tonic-gate 	if (j != 0) {
645*7c478bd9Sstevel@tonic-gate 		if (silent == NOT_SILENT)
646*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
647*7c478bd9Sstevel@tonic-gate 			    "probe_stack failed. address=0x%08X; "
648*7c478bd9Sstevel@tonic-gate 			    "probe=0x%02X; content = %d\n"),
649*7c478bd9Sstevel@tonic-gate 			    (caddr_t)last_fail_address, last_fail, j);
650*7c478bd9Sstevel@tonic-gate 
651*7c478bd9Sstevel@tonic-gate 		exit(FAIL_ZERO);    /* test failed at least once */
652*7c478bd9Sstevel@tonic-gate 	}
653*7c478bd9Sstevel@tonic-gate 	exit(EXIT_SUCCESS);
654*7c478bd9Sstevel@tonic-gate }
655*7c478bd9Sstevel@tonic-gate 
656*7c478bd9Sstevel@tonic-gate static void
657*7c478bd9Sstevel@tonic-gate probe_hole(int test_type)
658*7c478bd9Sstevel@tonic-gate {
659*7c478bd9Sstevel@tonic-gate 	long i;
660*7c478bd9Sstevel@tonic-gate 	/* LINTED */
661*7c478bd9Sstevel@tonic-gate 	volatile unsigned char probe;
662*7c478bd9Sstevel@tonic-gate 	unsigned char *probe_adr;
663*7c478bd9Sstevel@tonic-gate 	void *address;
664*7c478bd9Sstevel@tonic-gate 
665*7c478bd9Sstevel@tonic-gate 	address = sbrk(0);  /* current end data + 1 */
666*7c478bd9Sstevel@tonic-gate 
667*7c478bd9Sstevel@tonic-gate 	if (address == (void *)-1) {
668*7c478bd9Sstevel@tonic-gate 		print_message(gettext("Test program logic error\n"));
669*7c478bd9Sstevel@tonic-gate 		exit(FAIL_ABORT);
670*7c478bd9Sstevel@tonic-gate 	}
671*7c478bd9Sstevel@tonic-gate 	if (test_type == PH_VALID) {
672*7c478bd9Sstevel@tonic-gate 		/* show that access works inside the  hole */
673*7c478bd9Sstevel@tonic-gate 		handler_exit_code = FAIL_SEGV;
674*7c478bd9Sstevel@tonic-gate 
675*7c478bd9Sstevel@tonic-gate 		probe_adr =  (unsigned char *)address - sizeof (char);
676*7c478bd9Sstevel@tonic-gate 
677*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < PAGESIZE; i++)
678*7c478bd9Sstevel@tonic-gate 			probe = *probe_adr--;
679*7c478bd9Sstevel@tonic-gate 
680*7c478bd9Sstevel@tonic-gate 		exit(EXIT_SUCCESS);
681*7c478bd9Sstevel@tonic-gate 	} else {
682*7c478bd9Sstevel@tonic-gate 		/* show that a trap occurs in the  hole */
683*7c478bd9Sstevel@tonic-gate 		handler_exit_code = PASS_SEGV;
684*7c478bd9Sstevel@tonic-gate 
685*7c478bd9Sstevel@tonic-gate 		address = (void *)P2ROUNDUP((uintptr_t)address, PAGESIZE);
686*7c478bd9Sstevel@tonic-gate 		probe_adr = (unsigned char *)address;
687*7c478bd9Sstevel@tonic-gate 
688*7c478bd9Sstevel@tonic-gate 		probe = *probe_adr;
689*7c478bd9Sstevel@tonic-gate 		exit(FAIL_SEGV);	/* expected SEGV, didn't get it */
690*7c478bd9Sstevel@tonic-gate 	}
691*7c478bd9Sstevel@tonic-gate }
692*7c478bd9Sstevel@tonic-gate 
693*7c478bd9Sstevel@tonic-gate /*
694*7c478bd9Sstevel@tonic-gate  * Catch signal, child to parent
695*7c478bd9Sstevel@tonic-gate  */
696*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
697*7c478bd9Sstevel@tonic-gate void
698*7c478bd9Sstevel@tonic-gate handler(int signal)
699*7c478bd9Sstevel@tonic-gate {
700*7c478bd9Sstevel@tonic-gate 	done_memory_grab = 1;
701*7c478bd9Sstevel@tonic-gate }
702*7c478bd9Sstevel@tonic-gate /*
703*7c478bd9Sstevel@tonic-gate  * memory_type:  Determine whether a given executable file is compiled
704*7c478bd9Sstevel@tonic-gate  * as 32 or 64 bit.
705*7c478bd9Sstevel@tonic-gate  *
706*7c478bd9Sstevel@tonic-gate  * The following code was stolen from isainfo (1)
707*7c478bd9Sstevel@tonic-gate  */
708*7c478bd9Sstevel@tonic-gate 
709*7c478bd9Sstevel@tonic-gate static int
710*7c478bd9Sstevel@tonic-gate memory_type(const char *path) {
711*7c478bd9Sstevel@tonic-gate 	char *idarray;
712*7c478bd9Sstevel@tonic-gate 	Elf *elf;
713*7c478bd9Sstevel@tonic-gate 	int d;
714*7c478bd9Sstevel@tonic-gate 	int bits = 0;
715*7c478bd9Sstevel@tonic-gate 
716*7c478bd9Sstevel@tonic-gate 	if ((d = open(path, O_RDONLY)) < 0) {
717*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
718*7c478bd9Sstevel@tonic-gate 		    "cannot open: %s -- %s\n",
719*7c478bd9Sstevel@tonic-gate 		    path, strerror(errno));
720*7c478bd9Sstevel@tonic-gate 		return (bits);
721*7c478bd9Sstevel@tonic-gate 	}
722*7c478bd9Sstevel@tonic-gate 
723*7c478bd9Sstevel@tonic-gate 	if (elf_version(EV_CURRENT) == EV_NONE) {
724*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
725*7c478bd9Sstevel@tonic-gate 		    "internal error: ELF library out of date?\n");
726*7c478bd9Sstevel@tonic-gate 		(void) close(d);
727*7c478bd9Sstevel@tonic-gate 		return (bits);
728*7c478bd9Sstevel@tonic-gate 	}
729*7c478bd9Sstevel@tonic-gate 
730*7c478bd9Sstevel@tonic-gate 	elf = elf_begin(d, ELF_C_READ, (Elf *)0);
731*7c478bd9Sstevel@tonic-gate 	if (elf_kind(elf) != ELF_K_ELF) {
732*7c478bd9Sstevel@tonic-gate 		(void) elf_end(elf);
733*7c478bd9Sstevel@tonic-gate 		(void) close(d);
734*7c478bd9Sstevel@tonic-gate 		return (bits);
735*7c478bd9Sstevel@tonic-gate 	}
736*7c478bd9Sstevel@tonic-gate 
737*7c478bd9Sstevel@tonic-gate 	idarray = elf_getident(elf, 0);
738*7c478bd9Sstevel@tonic-gate 
739*7c478bd9Sstevel@tonic-gate 	if (idarray[EI_CLASS] == ELFCLASS32) {
740*7c478bd9Sstevel@tonic-gate 		bits = 32;
741*7c478bd9Sstevel@tonic-gate 	} else if (idarray[EI_CLASS] == ELFCLASS64) {
742*7c478bd9Sstevel@tonic-gate 		bits = 64;
743*7c478bd9Sstevel@tonic-gate 	}
744*7c478bd9Sstevel@tonic-gate 
745*7c478bd9Sstevel@tonic-gate 	(void) elf_end(elf);
746*7c478bd9Sstevel@tonic-gate 	(void) close(d);
747*7c478bd9Sstevel@tonic-gate 	return (bits);
748*7c478bd9Sstevel@tonic-gate }
749