This is xnu-11215.1.10. See this file in:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <ptrauth.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/sysctl.h>
#include <unistd.h>

#include <mach/mach_vm.h>

/*
 * ecc_test_helper is a convenience binary to induce various ECC errors
 * it's used by ECC-related tests: XNU unit tests and end-2-end coreos-tests
 */


int verbose = 0;
#define PRINTF(...) \
	if (verbose) { \
	        printf(__VA_ARGS__); \
	}

__attribute__((noinline))
static void
foo(void)
{
	PRINTF("In foo()\n");
	fflush(stdout);
}

volatile struct data {
	char buffer1[16 * 1024];
	int big_data[16 * 1024];
	char buffer2[16 * 1024];
} x = {
	.big_data = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
	}
};

/*
 * volatile to stop the compiler from optimizing away calls to atan()
 */
volatile double zero = 0.0;


typedef enum TestCase {
	Yfoo,
	Xfoo,
	Yatan,
	Xatan,
	Xclean,
	Xdirty,
	Xcopyout,
	Xmmap_clean,
	Xmmap_dirty,
	Xwired,
	kernel,

	BAD_TEST_CASE
} TestCase;

typedef struct{
	char *key;
	enum TestCase val;
} testcase_t;

#define testCase(name) {#name, name}

static testcase_t testcases[] = {
	testCase(Yfoo),
	testCase(Xfoo),
	testCase(Yatan),
	testCase(Xatan),
	testCase(Xclean),
	testCase(Xdirty),
	testCase(Xmmap_clean),
	testCase(Xmmap_dirty),
	testCase(Xcopyout),
	testCase(kernel),
	testCase(Xwired)
};

TestCase
get_testcase(char *key)
{
	int i;
	for (i = 0; i < sizeof(testcases) / sizeof(testcase_t); i++) {
		testcase_t elem = testcases[i];
		if (strcmp(elem.key, key) == 0) {
			return elem.val;
		}
	}
	return BAD_TEST_CASE;
}

int
main(int argc, char **argv)
{
	void *addr;
	int *page;
	size_t s = sizeof(addr);
	int err;
	static volatile int readval;
	static volatile double readval_d;

	/*
	 * check for -v for verbose output
	 */
	if (argc > 1 && strcmp(argv[1], "-v") == 0) {
		verbose = 1;
	}

	/*
	 * needs to run as root for sysctl
	 */
	if (geteuid() != 0) {
		printf("Test not running as root, exiting\n");
		exit(-1);
	}

	/*
	 * The argument determines what test to try.
	 * "Y{name}" is a test, "X{name}" does the test after injecting an ECC error
	 *
	 * Tests:
	 * "foo" - invoke a local TEXT function.
	 * "atan" - invoke a shared library TEXT function.
	 * "clean" - read from a clean DATA page
	 * "dirty" - read from a dirty DATA page
	 * "mmap_clean" - read from a clean mmap'd page
	 * "mmap_dirty" - read from a dirty mmap'd page
	 */
	switch (get_testcase(argv[argc - 1])) {
	case Yfoo:
		foo();
		break;
	case Xfoo:
		PRINTF("Warm up call to foo()\n");
		foo();

		addr = (void *)ptrauth_strip(&foo, ptrauth_key_function_pointer);
		err = sysctlbyname("vm.inject_ecc", NULL, NULL, &addr, s);

		PRINTF("Calling foo() after injection\n");
		foo();

		break;
	case Yatan:
		readval_d = atan(zero);
		PRINTF("atan(0) is %g\n", readval_d);
		break;
	case Xatan:
		readval_d = atan(zero);
		PRINTF("Warmup call to atan(0) is %g\n", readval_d);

		addr = (void *)ptrauth_strip(&atan, ptrauth_key_function_pointer);
		err = sysctlbyname("vm.inject_ecc", NULL, NULL, &addr, s);

		readval_d = atan(zero);
		PRINTF("After injection, atan(0) is %g\n", readval_d);
		break;
	case Xclean:
		readval = x.big_data[35];
		PRINTF("initial read of clean x.big_data[35] is %d\n", readval);

		addr = (void *)&x.big_data[35];
		err = sysctlbyname("vm.inject_ecc", NULL, NULL, &addr, s);

		readval = x.big_data[35];
		PRINTF("After injection, read of x.big_data[35] is %d\n", readval);
		break;
	case Xdirty:
		x.big_data[36] = (int)random();
		PRINTF("initial read of dirty x.big_data[36] is %d\n", x.big_data[36]);

		addr = (void *)&x.big_data[36];
		err = sysctlbyname("vm.inject_ecc", NULL, NULL, &addr, s);

		readval = x.big_data[36];
		PRINTF("After injection, read of x.big_data[36] is %d\n", readval);
		break;
	case Xmmap_clean:
		page = (int *)mmap(NULL, PAGE_SIZE * 3, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, 0, 0);
		page = (int *)((char *)page + PAGE_SIZE);

		readval = *page;
		PRINTF("initial read of clean page %p is %d\n", page, readval);

		err = sysctlbyname("vm.inject_ecc", NULL, NULL, &page, s);

		readval = *page;
		PRINTF("second read of page is %d\n", readval);
		break;
	case Xmmap_dirty:
		page = (int *) mmap(NULL, PAGE_SIZE * 3, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, 0, 0);
		page = (int *)((char *)page + PAGE_SIZE);

		*page = 0xFFFF;
		PRINTF("initial read of dirty page %p is %d (after write)\n", page, *page);

		err = sysctlbyname("vm.inject_ecc", NULL, NULL, &page, s);

		readval = *page;
		PRINTF("second read of page is %d\n", readval);
		break;
	case Xcopyout:
		x.big_data[37] = (int)random();
		PRINTF("initial read of dirty x.big_data[37] is %d\n", x.big_data[37]);

		addr = (void *)&x.big_data[37];
		err = sysctlbyname("vm.inject_ecc_copyout", NULL, NULL, &addr, s);
		if (err) {
			PRINTF("copyout return %d\n", err);
			exit(err);
		}

		readval = x.big_data[37];
		PRINTF("After injection, read of dirty x.big_data[37] is %d\n", readval);
		break;
	case Xwired:
		page = (int *) mmap(NULL, PAGE_SIZE * 3, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, 0, 0);
		page = (int *)((char *)page + PAGE_SIZE);
		PRINTF("page addr %p\n", page);
		if (mlock(page, PAGE_SIZE)) {
			printf("Failed to wire, errno: %d", errno);
			exit(0);
		}

		err = sysctlbyname("vm.inject_ecc", NULL, NULL, &page, s);

		readval = *page;
		PRINTF("wire trigger value: %d", readval);

		break;
	case kernel:
		PRINTF("Inducing ECC on kernel page\n");

		addr = (void *)1;         /* used to flag some kernel page */
		err = sysctlbyname("vm.inject_ecc", NULL, NULL, &addr, s);
		exit(0);

		break;
	case BAD_TEST_CASE:
		printf("Unknown test case\n\n");
		printf("Valid tests:\n");
		for (int i = 0; i < sizeof(testcases) / sizeof(testcase_t); i++) {
			testcase_t elem = testcases[i];
			printf("%d. %s\n", i + 1, elem.key);
		}
		printf("\nY{name} is a test, X{name} does the test after injecting an ECC error\n");

		exit(1);

		break;
	}

	exit(0);
}