Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | /* * Copyright (c) 2025 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. The rights granted to you under the License * may not be used to create, or enable the creation or redistribution of, * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ #include <sys/types.h> #include <sys/sysctl.h> #include <stdio.h> #include <darwintest.h> #include "test_utils.h" #include <sys/code_signing.h> #include "test_erm_sysctl.h" ERM_GLOBAL_META T_DECL(erm_sysctl_writer_can_write_when_ERM, "ensure the correctly entitled program can write the sysctl", ERM_ENABLED_META) { if (is_ERM_active()) { int ret = sysctlbyname(ERM_SYSCTL_NAME, NULL, NULL, (void*)sample_config, sample_config_len); T_ASSERT_POSIX_SUCCESS(ret, "erm sysctl could be written"); } else { T_SKIP("Running without ERM enabled, skipping..."); } } #if 0 // This test is removed because now TXM kills a process that is entitled for ERM when ERM is NOT active. // I keep this code here (even if commented out), in order to keep track of this special behavior change. T_DECL(erm_sysctl_writer_cant_write_when_no_ERM, "ensure the correctly entitled program can't write the sysctl when ERM is NOT active" ) { if (is_ERM_active()) { T_SKIP("Running with TrustedExecutionMonitor enabled, skipping..."); } else { int ret = sysctlbyname(ERM_SYSCTL_NAME, NULL, NULL, (void*)sample_config, sample_config_len); T_ASSERT_POSIX_FAILURE(ret, ENOENT, "erm sysctl could be written"); } } #endif T_DECL(erm_sysctl_writer_can_write_and_read, "ensure the correctly entitled program can write the sysctl then read it back", ERM_ENABLED_META) { if (is_ERM_active()) { int ret = sysctlbyname(ERM_SYSCTL_NAME, NULL, NULL, (void*)sample_config, sample_config_len); T_ASSERT_POSIX_SUCCESS(ret, "erm sysctl could be written"); size_t read_config_len = sample_config_len; void* read_config = malloc(read_config_len); ret = sysctlbyname(ERM_SYSCTL_NAME, read_config, &read_config_len, NULL, 0); T_ASSERT_POSIX_SUCCESS(ret, "erm sysctl could be read"); T_EXPECT_EQ(read_config_len, sample_config_len, "erm sysctl read correct size"); T_EXPECT_EQ_ULONG(*(unsigned long*)read_config, *(unsigned long*)sample_config, "erm sysctl read correct data"); free(read_config); } else { T_SKIP("Running without ERM enabled, skipping..."); } } T_DECL(erm_sysctl_writer_can_write_and_read_smaller_buffer, "ensure we handle correctly when user space provides a too small buffer", ERM_ENABLED_META) { if (is_ERM_active()) { int ret = sysctlbyname(ERM_SYSCTL_NAME, NULL, NULL, (void*)sample_config, sample_config_len); T_ASSERT_POSIX_SUCCESS(ret, "erm sysctl could be written"); // we provide a read buffer of only 2 bytes (the whole config is 8 bytes) const size_t read_config_small_len = sizeof(short); size_t read_config_len = read_config_small_len; void* read_config = malloc(read_config_len); ret = sysctlbyname(ERM_SYSCTL_NAME, read_config, &read_config_len, NULL, 0); T_ASSERT_POSIX_FAILURE(ret, ENOMEM, "erm sysctl couldn't be read"); T_EXPECT_EQ(read_config_len, sample_config_len, "we should have received the actual config size"); free(read_config); } else { T_SKIP("Running without ERM enabled, skipping..."); } } T_DECL(erm_sysctl_writer_can_write_and_read_bigger_buffer, "ensure we handle correctly when user space provides a too big buffer", ERM_ENABLED_META) { if (is_ERM_active()) { int ret = sysctlbyname(ERM_SYSCTL_NAME, NULL, NULL, (void*)sample_config, sample_config_len); T_ASSERT_POSIX_SUCCESS(ret, "erm sysctl could be written"); // we provide a read buffer that is bigger than necessary const size_t read_config_big_len = 2 * sizeof(long); size_t read_config_len = read_config_big_len; void* read_config = malloc(read_config_len); // this part will be overriten by the sysctl ((long*)read_config)[0] = 0; // this part should not be touched unsigned long extra_data = 0x123456789abcdef0; ((unsigned long*)read_config)[1] = extra_data; ret = sysctlbyname(ERM_SYSCTL_NAME, read_config, &read_config_len, NULL, 0); T_ASSERT_POSIX_SUCCESS(ret, "erm sysctl could be read"); T_EXPECT_EQ(read_config_len, sample_config_len, "erm sysctl read correct size"); T_EXPECT_EQ_ULONG(*(unsigned long*)read_config, *(unsigned long*)sample_config, "erm sysctl read correct data"); T_EXPECT_EQ_ULONG(((unsigned long*)read_config)[1], extra_data, "erm sysctl doesn't touch this part of the buffer"); free(read_config); } else { T_SKIP("Running without ERM enabled, skipping..."); } } T_DECL(erm_sysctl_writer_refuses_oversized_config, "check the sysctl doesn't accept oversized config", ERM_ENABLED_META) { if (is_ERM_active()) { size_t big_buffer_len = 2 * PAGE_SIZE; void* big_buffer = malloc(big_buffer_len); int ret = sysctlbyname(ERM_SYSCTL_NAME, NULL, NULL, big_buffer, big_buffer_len); T_ASSERT_POSIX_FAILURE(ret, EINVAL, "erm sysctl refuses oversized buffers"); free(big_buffer); } else { T_SKIP("Running without ERM enabled, skipping..."); } } |