Loading...
--- xnu/xnu-12377.101.15/tests/libmalloc_apple_array.c
+++ /dev/null
@@ -1,335 +0,0 @@
-#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", ¤t_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", ¤t_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", ¤t_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", ¤t_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="
-
-#define SECURITY_CONFIG_KEY "security_config="
-
-
-/*
- * 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(hardened_browser_flags_t, uint32_t, {
- BrowserHostEntitlementMask = 0x01,
- BrowserGPUEntitlementMask = 0x02,
- BrowserNetworkEntitlementMask = 0x04,
- BrowserWebContentEntitlementMask = 0x08,
-});
-
-T_DECL(libmalloc_hardened_browser_present,
- "platform restrictions 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");
- free(apple_array);
-
- /* 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);
-}
-
-#define SECURITY_CONFIG_HARDENED_HEAP_ENTRY (0x01)
-#define SECURITY_CONFIG_TPRO_ENTRY (0x02)
-
-T_DECL(libmalloc_security_config_hardened_heap_entitlements,
- "parse security_config values to verify security configs hardened_heap enablement/disablement",
- T_META_ASROOT(false))
-{
- uint64_t apple_array_val = 0;
- size_t num_array_entries = 0;
- char **apple_array;
- bool found = false;
-
- apple_array = get_apple_array(&num_array_entries, "tools/print_apple_array_hardened_proc");
- found = get_apple_array_key(apple_array, num_array_entries, &apple_array_val, SECURITY_CONFIG_KEY);
- T_ASSERT_TRUE(found, "Found " SECURITY_CONFIG_KEY " in apple array");
-
- /* Let's start parsing the security config, to see what's enabled. */
- T_EXPECT_FALSE(apple_array_val & SECURITY_CONFIG_HARDENED_HEAP_ENTRY, "Hardened-heap is disabled");
- free(apple_array);
-
- apple_array = get_apple_array(&num_array_entries, "tools/print_apple_array_hardened_heap");
- found = get_apple_array_key(apple_array, num_array_entries, &apple_array_val, SECURITY_CONFIG_KEY);
- T_ASSERT_TRUE(found, "Found " SECURITY_CONFIG_KEY " in apple array");
-
- T_EXPECT_TRUE(apple_array_val & SECURITY_CONFIG_HARDENED_HEAP_ENTRY, "Hardened-heap is enabled");
- free(apple_array);
-
- /* Verify that the same config is mirrored with the com.apple.security namespace */
- apple_array = get_apple_array(&num_array_entries, "tools/print_apple_array_hardened_heap_security");
- found = get_apple_array_key(apple_array, num_array_entries, &apple_array_val, SECURITY_CONFIG_KEY);
- T_ASSERT_TRUE(found, "Found " SECURITY_CONFIG_KEY " in apple array");
-
- T_EXPECT_TRUE(apple_array_val & SECURITY_CONFIG_HARDENED_HEAP_ENTRY, "Hardened-heap is enabled");
- free(apple_array);
-}
-
-
-T_DECL(libmalloc_hardened_browser_absent,
- "platform restrictions 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 */