This is xnu-11215.1.10. See this file in:
#include <errno.h>
#include <stdlib.h>
#include <libgen.h>
#include <limits.h>
#include <mach-o/dyld.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <xlocale.h>

#include <darwintest.h>
#include <darwintest_utils.h>

#include "drop_priv.h"
#include "test_utils.h"

#if ENTITLED
#define SET_TREATMENT_ID set_treatment_id_entitled
#define SET_TREATMENT_ID_DESCR "Can set treatment id with entitlement"
#else /* ENTITLED */
#define SET_TREATMENT_ID set_treatment_id_unentitled
#define SET_TREATMENT_ID_DESCR "Can't set treatment id without entitlement"
#endif /* ENTITLED */

T_DECL(SET_TREATMENT_ID, "Verifies that EXPERIMENT sysctls can only be set with the entitlement", T_META_ASROOT(false))
{
#define TEST_STR "testing"
#define IDENTIFIER_LENGTH 36

	int ret;
	errno_t err;
	char val[IDENTIFIER_LENGTH + 1] = {0};
	size_t len = sizeof(val);
	char new_val[IDENTIFIER_LENGTH + 1] = {0};

	if (!is_development_kernel()) {
		T_SKIP("skipping test on release kernel");
	}

	strlcpy(new_val, TEST_STR, sizeof(new_val));
	if (running_as_root()) {
		drop_priv();
	}

	ret = sysctlbyname("kern.trial_treatment_id", val, &len, new_val, strlen(new_val));
	err = errno;
#if ENTITLED
	len = sizeof(val);
	memset(new_val, 0, sizeof(new_val));
	T_ASSERT_POSIX_SUCCESS(ret, "set kern.trial_treatment_id");
	/* Cleanup. Set it back to the empty string. */
	ret = sysctlbyname("kern.trial_treatment_id", val, &len, new_val, 1);
	T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "reset kern.trial_treatment_id");
#else
	T_ASSERT_POSIX_FAILURE(ret, EPERM, "set kern.trial_treatment_id");
#endif /* ENTITLED */
}

#if ENTITLED
/* Check min and max value limits on numeric factors */
T_DECL(experiment_factor_numeric_limits,
    "Can only set factors within the legal range.",
    T_META_ASROOT(false))
{
#define kMinVal 5 /* The min value allowed for the testing factor. */
#define kMaxVal 10 /* The max value allowed for the testing factor. */
	errno_t err;
	int ret;
	unsigned int current_val;
	size_t len = sizeof(current_val);
	unsigned int new_val;

	if (running_as_root()) {
		drop_priv();
	}
	new_val = kMinVal - 1;
	ret = sysctlbyname("kern.testing_experiment_factor", &current_val, &len, &new_val, sizeof(new_val));
	err = errno;
	T_ASSERT_POSIX_FAILURE(ret, EINVAL, "set kern.testing_experiment_factor below range.");

	new_val = kMaxVal + 1;
	ret = sysctlbyname("kern.testing_experiment_factor", &current_val, &len, &new_val, sizeof(new_val));
	err = errno;
	T_ASSERT_POSIX_FAILURE(ret, EINVAL, "set kern.testing_experiment_factor above range.");

	new_val = kMaxVal;
	ret = sysctlbyname("kern.testing_experiment_factor", &current_val, &len, &new_val, sizeof(new_val));
	T_ASSERT_POSIX_SUCCESS(ret, "set kern.testing_experiment_factor at top of range.");

	new_val = kMinVal;
	ret = sysctlbyname("kern.testing_experiment_factor", &current_val, &len, &new_val, sizeof(new_val));
	T_ASSERT_POSIX_SUCCESS(ret, "set kern.testing_experiment_factor at bottom of range.");
}

static uint64_t original_libmalloc_experiment_value = 0;

static void
reset_libmalloc_experiment(void)
{
	int ret = sysctlbyname("kern.libmalloc_experiments", NULL, NULL, &original_libmalloc_experiment_value, sizeof(original_libmalloc_experiment_value));
	T_ASSERT_POSIX_SUCCESS(ret, "reset kern.libmalloc_experiments");
}

static void
set_libmalloc_experiment(uint64_t val)
{
	T_LOG("Setting kern.libmalloc_experiments to %llu", val);
	size_t len = sizeof(original_libmalloc_experiment_value);
	int ret = sysctlbyname("kern.libmalloc_experiments", &original_libmalloc_experiment_value, &len, &val, sizeof(val));
	T_ASSERT_POSIX_SUCCESS(ret, "set kern.libmalloc_experiments");
	T_ATEND(reset_libmalloc_experiment);
}

#define PRINT_APPLE_ARRAY_TOOL "tools/print_apple_array"
/*
 * Spawns a new binary and returns the contents of its apple array
 * (after libsystem initialization).
 */
static char **
get_apple_array(size_t *num_array_entries, const char * filename)
{
	if (filename == NULL) {
		filename = PRINT_APPLE_ARRAY_TOOL;
	}
	int ret;
	char stdout_path[MAXPATHLEN] = "apple_array.txt";
	dt_resultfile(stdout_path, MAXPATHLEN);
	int exit_status = 0, signum = 0;
	char binary_path[MAXPATHLEN], binary_dir[MAXPATHLEN];
	char *char_ret;
	const static size_t kMaxNumArguments = 256;
	size_t linecap = 0;
	ssize_t linelen = 0;
	char **apple_array;
	char **line = NULL;
	size_t num_lines = 0;
	FILE *stdout_f = NULL;
	uint32_t name_size = MAXPATHLEN;

	ret = _NSGetExecutablePath(binary_path, &name_size);
	T_QUIET; T_ASSERT_EQ(ret, 0, "_NSGetExecutablePath");
	char_ret = dirname_r(binary_path, binary_dir);
	T_QUIET; T_ASSERT_TRUE(char_ret != NULL, "dirname_r");
	snprintf(binary_path, MAXPATHLEN, "%s/%s", binary_dir, filename);

	char *launch_tool_args[] = {
		binary_path,
		NULL
	};
	pid_t child_pid;
	ret = dt_launch_tool(&child_pid, launch_tool_args, false, stdout_path, NULL);
	T_WITH_ERRNO; T_ASSERT_EQ(ret, 0, "dt_launch_tool: %s", binary_path);

	ret = dt_waitpid(child_pid, &exit_status, &signum, 60 * 5);
	T_ASSERT_EQ(ret, 1, "dt_waitpid");
	T_QUIET; T_ASSERT_EQ(exit_status, 0, "dt_waitpid: exit_status");
	T_QUIET; T_ASSERT_EQ(signum, 0, "dt_waitpid: signum");

	stdout_f = fopen(stdout_path, "r");
	T_WITH_ERRNO; T_ASSERT_NOTNULL(stdout_f, "open(%s)", stdout_path);
	apple_array = calloc(kMaxNumArguments, sizeof(char *));
	T_QUIET; T_ASSERT_NOTNULL(apple_array, "calloc: %lu\n", sizeof(char *) * kMaxNumArguments);
	while (num_lines < kMaxNumArguments) {
		line = &(apple_array[num_lines++]);
		linecap = 0;
		linelen = getline(line, &linecap, stdout_f);
		if (linelen == -1) {
			break;
		}
	}
	*num_array_entries = num_lines - 1;

	ret = fclose(stdout_f);
	T_ASSERT_POSIX_SUCCESS(ret, "fclose(%s)", stdout_path);

	return apple_array;
}

#define LIBMALLOC_EXPERIMENT_FACTORS_KEY "MallocExperiment="

#define HARDENED_RUNTIME_KEY "HardenedRuntime="


/*
 * Get the value of the key in the apple array.
 * Returns true iff the key is present.
 */
static bool
get_apple_array_key(char **apple_array, size_t num_array_entries, uint64_t *factors, const char *key)
{
	bool found = false;
	for (size_t i = 0; i < num_array_entries; i++) {
		char *str = apple_array[i];
		if (strstr(str, key)) {
			found = true;
			if (factors != NULL) {
				str = strchr(str, '=');
				T_ASSERT_NOTNULL(str, "skip over =");
				++str;
				*factors = strtoull_l(str, NULL, 16, NULL);
			}
			break;
		}
	}
	return found;
}

/* libmalloc relies on these values not changing. If they change,
 * you need to update the values in that project as well */
__options_decl(HR_flags_t, uint32_t, {
	BrowserHostEntitlementMask       = 0x01,
	BrowserGPUEntitlementMask        = 0x02,
	BrowserNetworkEntitlementMask    = 0x04,
	BrowserWebContentEntitlementMask = 0x08,
});

T_DECL(libmalloc_hardened_binary_present,
    "hardened binary flags show up in apple array",
    T_META_ASROOT(false))
{
	uint64_t apple_array_val = 0;
	size_t num_array_entries = 0;
	char **apple_array;
	bool found = false;

	/* These are the entitlements on the HR1 binary */
	uint32_t mask_val = BrowserHostEntitlementMask | BrowserGPUEntitlementMask | BrowserWebContentEntitlementMask;
	apple_array = get_apple_array(&num_array_entries, "tools/print_apple_array_HR1");
	found = get_apple_array_key(apple_array, num_array_entries, &apple_array_val, HARDENED_RUNTIME_KEY);
	T_ASSERT_TRUE(found, "Found " HARDENED_RUNTIME_KEY " in apple array");
	T_ASSERT_EQ(apple_array_val, mask_val, "Bitmask value matches");

	/* These are the entitlements on the HR2 binary */
	mask_val = BrowserGPUEntitlementMask | BrowserNetworkEntitlementMask;
	apple_array = get_apple_array(&num_array_entries, "tools/print_apple_array_HR2");
	found = get_apple_array_key(apple_array, num_array_entries, &apple_array_val, HARDENED_RUNTIME_KEY);
	T_ASSERT_TRUE(found, "Found " HARDENED_RUNTIME_KEY " in apple array");
	T_ASSERT_EQ(apple_array_val, mask_val, "Bitmask value matches");
	free(apple_array);
}


T_DECL(libmalloc_hardened_binary_absent,
    "hardened binary flags do not show up in apple array for normal third party processes",
    T_META_ASROOT(false))
{
	uint64_t new_val, apple_array_val = 0;
	size_t num_array_entries = 0;
	char **apple_array;
	bool found = false;
	apple_array = get_apple_array(&num_array_entries, NULL); // todo apple_array_3p?
	found = get_apple_array_key(apple_array, num_array_entries, &apple_array_val, HARDENED_RUNTIME_KEY);
	T_ASSERT_TRUE(!found, "Did not find " HARDENED_RUNTIME_KEY " in apple array");
	free(apple_array);
}

T_DECL(libmalloc_experiment,
    "libmalloc experiment flags show up in apple array if we're doing an experiment",
    T_META_ASROOT(false))
{
	uint64_t new_val, apple_array_val = 0;
	size_t num_array_entries = 0;
	char **apple_array;
	bool found = false;

	if (running_as_root()) {
		drop_priv();
	}
	new_val = (1ULL << 63) - 1;
	set_libmalloc_experiment(new_val);

	apple_array = get_apple_array(&num_array_entries, NULL);
	found = get_apple_array_key(apple_array, num_array_entries, &apple_array_val, LIBMALLOC_EXPERIMENT_FACTORS_KEY);
	T_ASSERT_TRUE(found, "Found " LIBMALLOC_EXPERIMENT_FACTORS_KEY " in apple array");
	T_ASSERT_EQ(apple_array_val, new_val, "Experiment value matches");
	free(apple_array);
}

T_DECL(libmalloc_experiment_not_in_array,
    "libmalloc experiment flags do not show up in apple array if we're not doing an experiment",
    T_META_ASROOT(false))
{
	size_t num_array_entries = 0;
	char **apple_array;
	bool found = false;

	if (running_as_root()) {
		drop_priv();
	}
	set_libmalloc_experiment(0);

	apple_array = get_apple_array(&num_array_entries, NULL);
	found = get_apple_array_key(apple_array, num_array_entries, NULL, LIBMALLOC_EXPERIMENT_FACTORS_KEY);
	T_ASSERT_TRUE(!found, "Did not find " LIBMALLOC_EXPERIMENT_FACTORS_KEY " in apple array");
	free(apple_array);
}
#endif /* ENTITLED */