1*19c3b8c2SApple OSS Distributions #include <stdio.h>
2*19c3b8c2SApple OSS Distributions #include <stdlib.h>
3*19c3b8c2SApple OSS Distributions #include <unistd.h>
4*19c3b8c2SApple OSS Distributions #include <darwintest.h>
5*19c3b8c2SApple OSS Distributions #include <mach/mach.h>
6*19c3b8c2SApple OSS Distributions #include <mach/mach_vm.h>
7*19c3b8c2SApple OSS Distributions #include <sys/sysctl.h>
8*19c3b8c2SApple OSS Distributions #include <spawn.h>
9*19c3b8c2SApple OSS Distributions #include <signal.h>
10*19c3b8c2SApple OSS Distributions #import <System/sys/codesign.h>
11*19c3b8c2SApple OSS Distributions
12*19c3b8c2SApple OSS Distributions #define IKOT_TASK_CONTROL 2
13*19c3b8c2SApple OSS Distributions
14*19c3b8c2SApple OSS Distributions T_GLOBAL_META(
15*19c3b8c2SApple OSS Distributions T_META_NAMESPACE("xnu.ipc"),
16*19c3b8c2SApple OSS Distributions T_META_RADAR_COMPONENT_NAME("xnu"),
17*19c3b8c2SApple OSS Distributions T_META_RADAR_COMPONENT_VERSION("IPC"),
18*19c3b8c2SApple OSS Distributions T_META_RUN_CONCURRENTLY(TRUE));
19*19c3b8c2SApple OSS Distributions
20*19c3b8c2SApple OSS Distributions static void
test_extract_immovable_task_port(pid_t pid)21*19c3b8c2SApple OSS Distributions test_extract_immovable_task_port(pid_t pid)
22*19c3b8c2SApple OSS Distributions {
23*19c3b8c2SApple OSS Distributions kern_return_t kr;
24*19c3b8c2SApple OSS Distributions mach_port_t tport = MACH_PORT_NULL;
25*19c3b8c2SApple OSS Distributions ipc_info_space_t space_info;
26*19c3b8c2SApple OSS Distributions ipc_info_name_array_t table;
27*19c3b8c2SApple OSS Distributions mach_msg_type_number_t tableCount;
28*19c3b8c2SApple OSS Distributions ipc_info_tree_name_array_t tree; /* unused */
29*19c3b8c2SApple OSS Distributions mach_msg_type_number_t treeCount; /* unused */
30*19c3b8c2SApple OSS Distributions
31*19c3b8c2SApple OSS Distributions mach_port_t extracted;
32*19c3b8c2SApple OSS Distributions mach_msg_type_name_t right;
33*19c3b8c2SApple OSS Distributions
34*19c3b8c2SApple OSS Distributions
35*19c3b8c2SApple OSS Distributions kr = task_for_pid(mach_task_self(), pid, &tport);
36*19c3b8c2SApple OSS Distributions T_EXPECT_MACH_SUCCESS(kr, "task_for_pid(), tport: 0x%x", tport);
37*19c3b8c2SApple OSS Distributions
38*19c3b8c2SApple OSS Distributions T_LOG("Target pid: %d", pid);
39*19c3b8c2SApple OSS Distributions
40*19c3b8c2SApple OSS Distributions if (pid == getpid()) {
41*19c3b8c2SApple OSS Distributions /* self extraction should succeed */
42*19c3b8c2SApple OSS Distributions kr = mach_port_extract_right(mach_task_self(), mach_task_self(), MACH_MSG_TYPE_COPY_SEND, &extracted, &right);
43*19c3b8c2SApple OSS Distributions T_EXPECT_MACH_SUCCESS(kr, "mach_port_extract_right() on immovable port in current space should succeed");
44*19c3b8c2SApple OSS Distributions } else {
45*19c3b8c2SApple OSS Distributions unsigned int kotype = 0, kobject = 0;
46*19c3b8c2SApple OSS Distributions mach_port_name_t tport_name = MACH_PORT_NULL;
47*19c3b8c2SApple OSS Distributions int tport_idx = 0;
48*19c3b8c2SApple OSS Distributions kr = mach_port_space_info(tport, &space_info, &table, &tableCount, &tree, &treeCount);
49*19c3b8c2SApple OSS Distributions T_EXPECT_MACH_SUCCESS(kr, "mach_port_space_info()");
50*19c3b8c2SApple OSS Distributions
51*19c3b8c2SApple OSS Distributions for (int i = 0; i < tableCount; i++) {
52*19c3b8c2SApple OSS Distributions T_LOG("Searching for task port..name: 0x%x", table[i].iin_name);
53*19c3b8c2SApple OSS Distributions kr = mach_port_kernel_object(tport, table[i].iin_name, &kotype, &kobject);
54*19c3b8c2SApple OSS Distributions if (KERN_SUCCESS == kr && kotype == IKOT_TASK_CONTROL) {
55*19c3b8c2SApple OSS Distributions tport_name = table[i].iin_name;
56*19c3b8c2SApple OSS Distributions tport_idx = i;
57*19c3b8c2SApple OSS Distributions break;
58*19c3b8c2SApple OSS Distributions } else if (kr) {
59*19c3b8c2SApple OSS Distributions T_LOG("mach_port_kernel_object() failed on name 0x%x, kr: 0x%x", table[i].iin_name, kr);
60*19c3b8c2SApple OSS Distributions }
61*19c3b8c2SApple OSS Distributions }
62*19c3b8c2SApple OSS Distributions
63*19c3b8c2SApple OSS Distributions if (!tport_name) {
64*19c3b8c2SApple OSS Distributions T_FAIL("Did not find task port in child's space");
65*19c3b8c2SApple OSS Distributions }
66*19c3b8c2SApple OSS Distributions T_LOG("Remote tport name: 0x%x", tport_name);
67*19c3b8c2SApple OSS Distributions kr = mach_port_extract_right(tport, tport_name, MACH_MSG_TYPE_COPY_SEND, &extracted, &right);
68*19c3b8c2SApple OSS Distributions T_EXPECT_EQ(kr, KERN_INVALID_CAPABILITY, "mach_port_extract_right() on immovable port in child's space should fail (no crash): 0x%x", kr);
69*19c3b8c2SApple OSS Distributions
70*19c3b8c2SApple OSS Distributions T_LOG("Still alive after extract right..");
71*19c3b8c2SApple OSS Distributions
72*19c3b8c2SApple OSS Distributions kr = mach_port_mod_refs(tport, tport_name, MACH_PORT_RIGHT_SEND, -table[tport_idx].iin_urefs);
73*19c3b8c2SApple OSS Distributions T_EXPECT_EQ(kr, KERN_INVALID_CAPABILITY, "mach_port_mod_refs() on pinned port in child's space should fail (no crash): 0x%x", kr);
74*19c3b8c2SApple OSS Distributions
75*19c3b8c2SApple OSS Distributions T_LOG("Still alive after deallocate..");
76*19c3b8c2SApple OSS Distributions }
77*19c3b8c2SApple OSS Distributions }
78*19c3b8c2SApple OSS Distributions
79*19c3b8c2SApple OSS Distributions T_DECL(extract_right_soft_fail, "Immovable/pinned violation on foreign task's space should not crash caller",
80*19c3b8c2SApple OSS Distributions T_META_CHECK_LEAKS(false))
81*19c3b8c2SApple OSS Distributions {
82*19c3b8c2SApple OSS Distributions uint32_t opts = 0;
83*19c3b8c2SApple OSS Distributions size_t size = sizeof(&opts);
84*19c3b8c2SApple OSS Distributions pid_t child_pid;
85*19c3b8c2SApple OSS Distributions kern_return_t ret;
86*19c3b8c2SApple OSS Distributions int status, fd[2], fd2[2];
87*19c3b8c2SApple OSS Distributions
88*19c3b8c2SApple OSS Distributions T_LOG("Check if immovable control port has been enabled\n");
89*19c3b8c2SApple OSS Distributions ret = sysctlbyname("kern.ipc_control_port_options", &opts, &size, NULL, 0);
90*19c3b8c2SApple OSS Distributions
91*19c3b8c2SApple OSS Distributions if (!ret && (opts & 0x08) == 0) {
92*19c3b8c2SApple OSS Distributions T_SKIP("1p immovable control port hard enforcement isn't enabled");
93*19c3b8c2SApple OSS Distributions }
94*19c3b8c2SApple OSS Distributions
95*19c3b8c2SApple OSS Distributions /* extracting mach_task_self() should succeed */
96*19c3b8c2SApple OSS Distributions test_extract_immovable_task_port(getpid());
97*19c3b8c2SApple OSS Distributions
98*19c3b8c2SApple OSS Distributions ret = pipe(fd);
99*19c3b8c2SApple OSS Distributions T_EXPECT_NE(ret, -1, "pipe creation");
100*19c3b8c2SApple OSS Distributions
101*19c3b8c2SApple OSS Distributions ret = pipe(fd2);
102*19c3b8c2SApple OSS Distributions T_EXPECT_NE(ret, -1, "pipe creation2");
103*19c3b8c2SApple OSS Distributions
104*19c3b8c2SApple OSS Distributions child_pid = fork();
105*19c3b8c2SApple OSS Distributions
106*19c3b8c2SApple OSS Distributions if (child_pid < 0) {
107*19c3b8c2SApple OSS Distributions T_FAIL("fork failed()");
108*19c3b8c2SApple OSS Distributions }
109*19c3b8c2SApple OSS Distributions
110*19c3b8c2SApple OSS Distributions if (child_pid == 0) {
111*19c3b8c2SApple OSS Distributions char data[6];
112*19c3b8c2SApple OSS Distributions close(fd[0]);
113*19c3b8c2SApple OSS Distributions close(fd2[1]);
114*19c3b8c2SApple OSS Distributions write(fd[1], "wakeup", 6); /* Sync point 1 */
115*19c3b8c2SApple OSS Distributions close(fd[1]);
116*19c3b8c2SApple OSS Distributions
117*19c3b8c2SApple OSS Distributions read(fd2[0], data, 6); /* Sync point 2 */
118*19c3b8c2SApple OSS Distributions close(fd2[0]);
119*19c3b8c2SApple OSS Distributions } else {
120*19c3b8c2SApple OSS Distributions char data[6];
121*19c3b8c2SApple OSS Distributions close(fd[1]);
122*19c3b8c2SApple OSS Distributions close(fd2[0]);
123*19c3b8c2SApple OSS Distributions read(fd[0], data, 6); /* Sync point 1 */
124*19c3b8c2SApple OSS Distributions close(fd[0]);
125*19c3b8c2SApple OSS Distributions
126*19c3b8c2SApple OSS Distributions /* extracting child's immovable task port should fail without crash */
127*19c3b8c2SApple OSS Distributions test_extract_immovable_task_port(child_pid);
128*19c3b8c2SApple OSS Distributions
129*19c3b8c2SApple OSS Distributions write(fd2[1], "wakeup", 6); /* Sync point 2 */
130*19c3b8c2SApple OSS Distributions close(fd2[1]);
131*19c3b8c2SApple OSS Distributions
132*19c3b8c2SApple OSS Distributions kill(child_pid, SIGKILL);
133*19c3b8c2SApple OSS Distributions wait(&status);
134*19c3b8c2SApple OSS Distributions }
135*19c3b8c2SApple OSS Distributions }
136