xref: /xnu-10002.81.5/tests/ecc_test_helper.c (revision 5e3eaea39dcf651e66cb99ba7d70e32cc4a99587)
1 #include <stdlib.h>
2 #include <unistd.h>
3 #include <stdio.h>
4 #include <sys/sysctl.h>
5 #include <ptrauth.h>
6 #include <math.h>
7 #include <string.h>
8 #include <errno.h>
9 
10 int verbose = 0;
11 #define PRINTF(...) \
12 	if (verbose) { \
13 	        printf(__VA_ARGS__); \
14 	}
15 
16 __attribute__((noinline))
17 static void
foo(void)18 foo(void)
19 {
20 	PRINTF("In foo()\n");
21 	fflush(stdout);
22 }
23 
24 volatile struct data {
25 	char buffer1[16 * 1024];
26 	int big_data[16 * 1204];
27 	char buffer2[16 * 1024];
28 } x = {
29 	.big_data = {
30 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
31 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
32 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
33 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
34 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
35 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
36 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
37 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
38 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
39 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
40 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
41 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
42 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
43 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
44 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
45 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
46 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
47 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
48 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
49 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
50 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
51 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
52 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
53 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
54 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
55 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
56 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
57 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
58 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
59 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
60 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
61 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
62 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
63 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
64 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
65 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
66 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
67 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
68 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
69 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
70 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
71 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
72 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
73 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
74 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
75 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
76 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
77 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
78 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
79 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
80 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
81 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
82 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
83 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
84 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
85 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
86 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
87 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
88 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
89 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
90 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
91 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
92 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
93 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
94 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
95 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
96 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
97 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
98 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
99 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
100 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
101 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
102 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
103 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
104 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
105 	}
106 };
107 
108 /*
109  * volatile to stop the compiler from optimizing away calls to atan()
110  */
111 volatile double zero = 0.0;
112 
113 int
main(int argc,char ** argv)114 main(int argc, char **argv)
115 {
116 	void *addr;
117 	size_t s = sizeof(addr);
118 	int err;
119 	int a;
120 
121 	/*
122 	 * needs to run as root for sysctl.
123 	 */
124 	if (geteuid() != 0) {
125 		PRINTF("Test not running as root\n");
126 		exit(-1);
127 	}
128 
129 	/*
130 	 * check for -v for verbose output
131 	 */
132 	if (strcmp(argv[1], "-v") == 0) {
133 		verbose = 1;
134 	}
135 
136 	/*
137 	 * The argument determines what test to try.
138 	 *  "blahblah" is a test, "Xblahblah" does the test after inject an ECC error.
139 	 * Tests:
140 	 * "foo" - invoke a local text function.
141 	 * "atan" - invoke a shared library text function.
142 	 * "clean" - read from a clean data page
143 	 * "dirty" - read from a dirty data page
144 	 */
145 	if (strcmp(argv[argc - 1], "foo") == 0) {
146 		foo();
147 	} else if (strcmp(argv[argc - 1], "Xfoo") == 0) {
148 		PRINTF("Warm up call to foo()\n");
149 		foo();
150 		addr = (void *)ptrauth_strip(&foo, ptrauth_key_function_pointer);
151 		err = sysctlbyname("vm.inject_ecc", NULL, NULL, &addr, s);
152 		foo();
153 	} else if (strcmp(argv[argc - 1], "atan") == 0) {
154 		PRINTF("atan(0) is %g\n", atan(zero));
155 	} else if (strcmp(argv[argc - 1], "Xatan") == 0) {
156 		PRINTF("Warmup call to atan(0) is %g\n", atan(zero));
157 		addr = (void *)ptrauth_strip(&atan, ptrauth_key_function_pointer);
158 		err = sysctlbyname("vm.inject_ecc", NULL, NULL, &addr, s);
159 		PRINTF("atan(0) is %g\n", atan(zero));
160 	} else if (strcmp(argv[argc - 1], "clean") == 0) {
161 		PRINTF("x.big_data[35] is %d\n", x.big_data[35]);
162 	} else if (strcmp(argv[argc - 1], "Xclean") == 0) {
163 		PRINTF("initial read of x.big_data[35] is %d\n", x.big_data[35]);
164 
165 		addr = (void *)&x.big_data[35];
166 		err = sysctlbyname("vm.inject_ecc", NULL, NULL, &addr, s);
167 		PRINTF("second read of x.big_data[35] is %d\n", x.big_data[35]);
168 	} else if (strcmp(argv[argc - 1], "dirty") == 0) {
169 		x.big_data[35] = (int)random();
170 		PRINTF("x.big_data[35] is %d\n", x.big_data[35]);
171 	} else if (strcmp(argv[argc - 1], "Xdirty") == 0) {
172 		x.big_data[35] = (int)random();
173 		PRINTF("initial read of dirty x.big_data[35] is %d\n", x.big_data[35]);
174 
175 		addr = (void *)&x.big_data[35];
176 		err = sysctlbyname("vm.inject_ecc", NULL, NULL, &addr, s);
177 		PRINTF("second read of x.big_data[35] is %d\n", x.big_data[35]);
178 	} else if (strcmp(argv[argc - 1], "Xcopyout") == 0) {
179 		x.big_data[35] = (int)random();
180 		PRINTF("initial read of dirty x.big_data[35] is %d\n", x.big_data[35]);
181 
182 		addr = (void *)&x.big_data[35];
183 		err = sysctlbyname("vm.inject_ecc_copyout", NULL, NULL, &addr, s);
184 		if (err) {
185 			PRINTF("copyout return %d\n", err);
186 			exit(err);
187 		}
188 		PRINTF("2nd read of dirty x.big_data[35] is %d\n", x.big_data[35]);
189 	} else if (strcmp(argv[argc - 1], "kernel") == 0) {
190 		PRINTF("Inducing ECC on kernel page\n");
191 		addr = (void *)1; /* used to flag some kernel page */
192 		err = sysctlbyname("vm.inject_ecc", NULL, NULL, &addr, s);
193 		exit(0);
194 	} else {
195 		exit(-1);
196 	}
197 	exit(0);
198 }
199