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 | #include <stdio.h> #include <stdlib.h> #include <mach/mach.h> #include <mach/mach_port.h> #include <sys/code_signing.h> #include <sys/sysctl.h> #include <darwintest.h> T_GLOBAL_META( T_META_NAMESPACE("xnu.ipc"), T_META_RUN_CONCURRENTLY(TRUE), T_META_RADAR_COMPONENT_NAME("xnu"), T_META_RADAR_COMPONENT_VERSION("IPC"), T_META_TAG_VM_PREFERRED); #define countof(x) (sizeof(x) / sizeof(x[0])) static void expect_sigkill( void (^fn)(void), const char *description) { pid_t pid = fork(); T_QUIET; T_ASSERT_POSIX_SUCCESS(pid, "fork"); if (pid == 0) { fn(); T_ASSERT_FAIL("%s: did not receive SIGKILL", description); } else { int status = 0; T_QUIET; T_ASSERT_POSIX_SUCCESS(waitpid(pid, &status, 0), "waitpid"); T_EXPECT_EQ(WTERMSIG(status), SIGKILL, "%s exited with %d, expect SIGKILL", description, WTERMSIG(status)); } } T_DECL(mach_port_construct_at_most_one, "mach_port_construct at most one flag policy") { /* verify our at most one flag rule is enforced */ const uint32_t at_most_one_flags[] = { MPO_REPLY_PORT, MPO_CONNECTION_PORT, MPO_SERVICE_PORT, MPO_PROVISIONAL_REPLY_PORT, MPO_EXCEPTION_PORT, MPO_CONNECTION_PORT_WITH_PORT_ARRAY }; for (uint32_t i = 0; i < countof(at_most_one_flags) - 1; ++i) { for (uint32_t j = i + 1; j < countof(at_most_one_flags); ++j) { mach_port_t port; mach_port_options_t opts = { .flags = at_most_one_flags[i] | at_most_one_flags[j] }; kern_return_t kr = mach_port_construct(mach_task_self(), &opts, 0x0, &port); T_ASSERT_MACH_ERROR(kr, KERN_INVALID_ARGUMENT, "mach_port_construct failed for at most one flags"); } } } T_DECL(mach_port_construct_invalid_arguments_and_values, "mach_port_construct invalid arguments and values") { kern_return_t kr; mach_port_t port; mach_port_options_t conn_opts = { .flags = MPO_CONNECTION_PORT, .service_port_name = 0x0 }; kr = mach_port_construct(mach_task_self(), &conn_opts, 0x0, &port); T_ASSERT_MACH_ERROR(kr, KERN_INVALID_ARGUMENT, "MPO_CONNECTION_PORT failed on service_port_name"); conn_opts.service_port_name = MPO_ANONYMOUS_SERVICE; kr = mach_port_construct(mach_task_self(), &conn_opts, 0x0, &port); T_ASSERT_MACH_SUCCESS(kr, "MPO_CONNECTION_PORT succeeds with anonymous service name"); kr = mach_port_destruct(mach_task_self(), port, 0, 0); T_ASSERT_MACH_SUCCESS(kr, "destroy anonymous service name"); mach_port_options_t qlimit_opts = { .flags = MPO_QLIMIT, .mpl.mpl_qlimit = MACH_PORT_QLIMIT_MAX + 1 }; kr = mach_port_construct(mach_task_self(), &qlimit_opts, 0x0, &port); T_ASSERT_MACH_ERROR(kr, KERN_INVALID_VALUE, "MPO_QLIMIT failed on invalid value"); /* Enumerate on all unknown MPO flags */ mach_port_options_t unknown_flags_opts; for (uint32_t i = 0; i < sizeof(unknown_flags_opts.flags) * CHAR_BIT; ++i) { unknown_flags_opts.flags = MPO_UNUSED_BITS & (1 << i); if (unknown_flags_opts.flags != 0) { kr = mach_port_construct(mach_task_self(), &unknown_flags_opts, 0x0, &port); T_ASSERT_MACH_ERROR(kr, KERN_INVALID_ARGUMENT, "Unknown MPO flags 0x%x failed with KERN_INVALID_ARGUMENT", unknown_flags_opts.flags); } } } T_DECL(mach_port_construct_fatal_failure, "mach_port_construct kern defined fatal failures", T_META_IGNORECRASHES(".*mach_port_construct_errors.*"), T_META_ENABLED(!TARGET_OS_OSX && !TARGET_OS_BRIDGE)) { expect_sigkill(^{ mach_port_t port; mach_port_options_t opts = { .flags = MPO_CONNECTION_PORT_WITH_PORT_ARRAY }; (void)mach_port_construct(mach_task_self(), &opts, 0x0, &port); }, "passing MPO_CONNECTION_PORT_WITH_PORT_ARRAY without entitlement"); } T_DECL(mach_port_construct_kern_denied, "mach_port_construct kern defined failures", T_META_TAG_VM_PREFERRED, T_META_ENABLED(!TARGET_OS_OSX && !TARGET_OS_BRIDGE)) { kern_return_t kr; mach_port_t port; mach_port_options_t opts; /* * should fail because only TASK_GRAPHICS_SERVER is allowed to * use MPO_TG_BLOCK_TRACKING. */ opts.flags = MPO_TG_BLOCK_TRACKING; kr = mach_port_construct(mach_task_self(), &opts, 0x0, &port); T_ASSERT_MACH_ERROR(kr, KERN_DENIED, "MPO_TG_BLOCK_TRACKING failed with KERN_DENIED"); } |