xref: /xnu-8019.80.24/tests/mach_service_port.c (revision a325d9c4a84054e40bbe985afedcb50ab80993ea)
1*a325d9c4SApple OSS Distributions #include <darwintest.h>
2*a325d9c4SApple OSS Distributions #include <servers/bootstrap.h>
3*a325d9c4SApple OSS Distributions #include <mach/mach.h>
4*a325d9c4SApple OSS Distributions #include <mach/message.h>
5*a325d9c4SApple OSS Distributions #include <stdlib.h>
6*a325d9c4SApple OSS Distributions #include <sys/sysctl.h>
7*a325d9c4SApple OSS Distributions #include <unistd.h>
8*a325d9c4SApple OSS Distributions #include <mach/port.h>
9*a325d9c4SApple OSS Distributions #include <mach/mach_port.h>
10*a325d9c4SApple OSS Distributions #include <stdint.h>
11*a325d9c4SApple OSS Distributions #include <stdio.h>
12*a325d9c4SApple OSS Distributions #include <unistd.h>
13*a325d9c4SApple OSS Distributions #include <pthread.h>
14*a325d9c4SApple OSS Distributions #include <err.h>
15*a325d9c4SApple OSS Distributions #include <sysexits.h>
16*a325d9c4SApple OSS Distributions 
17*a325d9c4SApple OSS Distributions #include "notifyServer.h"
18*a325d9c4SApple OSS Distributions 
19*a325d9c4SApple OSS Distributions T_GLOBAL_META(T_META_RUN_CONCURRENTLY(true),
20*a325d9c4SApple OSS Distributions     T_META_NAMESPACE("xnu.ipc"),
21*a325d9c4SApple OSS Distributions     T_META_RADAR_COMPONENT_NAME("xnu"),
22*a325d9c4SApple OSS Distributions     T_META_RADAR_COMPONENT_VERSION("IPC"));
23*a325d9c4SApple OSS Distributions 
24*a325d9c4SApple OSS Distributions static mach_port_t service_port = MACH_PORT_NULL;
25*a325d9c4SApple OSS Distributions 
26*a325d9c4SApple OSS Distributions #define SP_CONTEXT (0x1803)
27*a325d9c4SApple OSS Distributions #define NEW_SP_CONTEXT (0x0318)
28*a325d9c4SApple OSS Distributions #define SERVICE_NAME "com.apple.testservice"
29*a325d9c4SApple OSS Distributions #define SERVICE_DOMAIN (1)
30*a325d9c4SApple OSS Distributions 
31*a325d9c4SApple OSS Distributions T_DECL(mach_service_port, "Create a port with a service port label", T_META_CHECK_LEAKS(false)) {
32*a325d9c4SApple OSS Distributions 	mach_port_t connection_port;
33*a325d9c4SApple OSS Distributions 	mach_port_t notify_port;
34*a325d9c4SApple OSS Distributions 	mach_port_t previous;
35*a325d9c4SApple OSS Distributions 	uint64_t fpid = 0;
36*a325d9c4SApple OSS Distributions 
37*a325d9c4SApple OSS Distributions 	struct mach_service_port_info sp_info = {};
38*a325d9c4SApple OSS Distributions 
39*a325d9c4SApple OSS Distributions 	strcpy(sp_info.mspi_string_name, SERVICE_NAME);
40*a325d9c4SApple OSS Distributions 	sp_info.mspi_domain_type = (uint8_t)SERVICE_DOMAIN;
41*a325d9c4SApple OSS Distributions 	kern_return_t kr;
42*a325d9c4SApple OSS Distributions 
43*a325d9c4SApple OSS Distributions 	mach_port_options_t opts = {
44*a325d9c4SApple OSS Distributions 		.flags = MPO_SERVICE_PORT | MPO_INSERT_SEND_RIGHT | MPO_CONTEXT_AS_GUARD | MPO_STRICT,
45*a325d9c4SApple OSS Distributions 		.service_port_info = &sp_info,
46*a325d9c4SApple OSS Distributions 	};
47*a325d9c4SApple OSS Distributions 
48*a325d9c4SApple OSS Distributions 	kr = mach_port_construct(mach_task_self(), &opts, SP_CONTEXT, &service_port);
49*a325d9c4SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_port_construct %u", service_port);
50*a325d9c4SApple OSS Distributions 
51*a325d9c4SApple OSS Distributions 	mach_port_options_t opts2 = {
52*a325d9c4SApple OSS Distributions 		.flags = MPO_CONNECTION_PORT,
53*a325d9c4SApple OSS Distributions 		.service_port_name = service_port,
54*a325d9c4SApple OSS Distributions 	};
55*a325d9c4SApple OSS Distributions 
56*a325d9c4SApple OSS Distributions 	kr = mach_port_construct(mach_task_self(), &opts2, 0x0, &connection_port);
57*a325d9c4SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_port_construct %u", connection_port);
58*a325d9c4SApple OSS Distributions 
59*a325d9c4SApple OSS Distributions 	kr = mach_port_is_connection_for_service(mach_task_self(), connection_port, service_port, &fpid);
60*a325d9c4SApple OSS Distributions 	if (kr != KERN_SUCCESS || kr != KERN_NOT_SUPPORTED) {
61*a325d9c4SApple OSS Distributions 		T_LOG("mach_port_is_connection_for_service kr = %d, fpid = %llu", kr, fpid);
62*a325d9c4SApple OSS Distributions 	}
63*a325d9c4SApple OSS Distributions 
64*a325d9c4SApple OSS Distributions 	// notification port for the service port to come back on
65*a325d9c4SApple OSS Distributions 	kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &notify_port);
66*a325d9c4SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_port_allocate notify_port");
67*a325d9c4SApple OSS Distributions 
68*a325d9c4SApple OSS Distributions 	kr = mach_port_insert_right(mach_task_self(), notify_port, notify_port, MACH_MSG_TYPE_MAKE_SEND);
69*a325d9c4SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_port_insert_right notify_port");
70*a325d9c4SApple OSS Distributions 
71*a325d9c4SApple OSS Distributions 	T_LOG("service port: 0x%x, notify port: 0x%x\n", service_port, notify_port);
72*a325d9c4SApple OSS Distributions 
73*a325d9c4SApple OSS Distributions 	kr = mach_port_request_notification(mach_task_self(), service_port, MACH_NOTIFY_PORT_DESTROYED, 0, notify_port,
74*a325d9c4SApple OSS Distributions 	    MACH_MSG_TYPE_MAKE_SEND_ONCE, &previous);
75*a325d9c4SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_port_request_notification service_port");
76*a325d9c4SApple OSS Distributions 	T_ASSERT_EQ(previous, MACH_PORT_NULL, "previous null");
77*a325d9c4SApple OSS Distributions 
78*a325d9c4SApple OSS Distributions 	/* Attempt to destroy port */
79*a325d9c4SApple OSS Distributions 	kr = mach_port_destruct(mach_task_self(), service_port, 0, SP_CONTEXT);
80*a325d9c4SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_port_destruct service_port");
81*a325d9c4SApple OSS Distributions 
82*a325d9c4SApple OSS Distributions 	/*
83*a325d9c4SApple OSS Distributions 	 * Recover the service port because the port must have been destroyed and sent the notification by now
84*a325d9c4SApple OSS Distributions 	 */
85*a325d9c4SApple OSS Distributions 	kr = mach_msg_server_once(notify_server, MACH_MSG_SIZE_RELIABLE, notify_port, MACH_RCV_TIMEOUT);
86*a325d9c4SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_msg_server_once notify_port");
87*a325d9c4SApple OSS Distributions 
88*a325d9c4SApple OSS Distributions 	T_LOG("done");
89*a325d9c4SApple OSS Distributions }
90*a325d9c4SApple OSS Distributions 
91*a325d9c4SApple OSS Distributions kern_return_t
do_mach_notify_port_destroyed(mach_port_t notify,mach_port_t name)92*a325d9c4SApple OSS Distributions do_mach_notify_port_destroyed(mach_port_t notify, mach_port_t name)
93*a325d9c4SApple OSS Distributions {
94*a325d9c4SApple OSS Distributions 	kern_return_t kr;
95*a325d9c4SApple OSS Distributions 
96*a325d9c4SApple OSS Distributions 	T_LOG("Received a service port destroyed notification notify = 0x%x name = 0x%x", notify, name);
97*a325d9c4SApple OSS Distributions 	if (name == MACH_PORT_NULL) {
98*a325d9c4SApple OSS Distributions 		T_FAIL("do_mach_notify_port_destroyed: MACH_PORT_NULL?");
99*a325d9c4SApple OSS Distributions 	}
100*a325d9c4SApple OSS Distributions 
101*a325d9c4SApple OSS Distributions 	if (name != service_port) {
102*a325d9c4SApple OSS Distributions 		T_FAIL("do_mach_notify_port_destroyed: name 0x%x != service_port: 0x%x", name, service_port);
103*a325d9c4SApple OSS Distributions 	}
104*a325d9c4SApple OSS Distributions 
105*a325d9c4SApple OSS Distributions 	struct mach_service_port_info sp_info = {};
106*a325d9c4SApple OSS Distributions 	kr = mach_port_get_service_port_info(mach_task_self(), service_port, &sp_info);
107*a325d9c4SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_port_get_service_port_info");
108*a325d9c4SApple OSS Distributions 
109*a325d9c4SApple OSS Distributions 	if (strcmp(sp_info.mspi_string_name, SERVICE_NAME)) {
110*a325d9c4SApple OSS Distributions 		T_FAIL("Service port name = %s is incorrect", sp_info.mspi_string_name);
111*a325d9c4SApple OSS Distributions 	}
112*a325d9c4SApple OSS Distributions 	T_ASSERT_EQ(sp_info.mspi_domain_type, SERVICE_DOMAIN, "Service domain = %u", sp_info.mspi_domain_type);
113*a325d9c4SApple OSS Distributions 
114*a325d9c4SApple OSS Distributions 	mach_port_guard_info_t mpgi = {SP_CONTEXT};
115*a325d9c4SApple OSS Distributions 	kr = mach_port_assert_attributes(mach_task_self(), service_port, MACH_PORT_GUARD_INFO, (mach_port_info_t)&mpgi, MACH_PORT_GUARD_INFO_COUNT);
116*a325d9c4SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_port_assert_attributes");
117*a325d9c4SApple OSS Distributions 
118*a325d9c4SApple OSS Distributions 	return KERN_SUCCESS;
119*a325d9c4SApple OSS Distributions }
120*a325d9c4SApple OSS Distributions 
121*a325d9c4SApple OSS Distributions kern_return_t
do_mach_notify_port_deleted(__unused mach_port_t notify,__unused mach_port_name_t name)122*a325d9c4SApple OSS Distributions do_mach_notify_port_deleted(__unused mach_port_t notify, __unused mach_port_name_t name)
123*a325d9c4SApple OSS Distributions {
124*a325d9c4SApple OSS Distributions 	return KERN_SUCCESS;
125*a325d9c4SApple OSS Distributions }
126*a325d9c4SApple OSS Distributions 
127*a325d9c4SApple OSS Distributions kern_return_t
do_mach_notify_no_senders(__unused mach_port_t notify,__unused mach_port_mscount_t mscount)128*a325d9c4SApple OSS Distributions do_mach_notify_no_senders(__unused mach_port_t notify, __unused mach_port_mscount_t mscount)
129*a325d9c4SApple OSS Distributions {
130*a325d9c4SApple OSS Distributions 	return KERN_SUCCESS;
131*a325d9c4SApple OSS Distributions }
132*a325d9c4SApple OSS Distributions 
133*a325d9c4SApple OSS Distributions kern_return_t
do_mach_notify_send_once(__unused mach_port_t notify)134*a325d9c4SApple OSS Distributions do_mach_notify_send_once(__unused mach_port_t notify)
135*a325d9c4SApple OSS Distributions {
136*a325d9c4SApple OSS Distributions 	return KERN_SUCCESS;
137*a325d9c4SApple OSS Distributions }
138*a325d9c4SApple OSS Distributions 
139*a325d9c4SApple OSS Distributions kern_return_t
do_mach_notify_dead_name(__unused mach_port_t notify,__unused mach_port_name_t name)140*a325d9c4SApple OSS Distributions do_mach_notify_dead_name(__unused mach_port_t notify, __unused mach_port_name_t name)
141*a325d9c4SApple OSS Distributions {
142*a325d9c4SApple OSS Distributions 	return KERN_SUCCESS;
143*a325d9c4SApple OSS Distributions }
144*a325d9c4SApple OSS Distributions 
145*a325d9c4SApple OSS Distributions #define SERVICE_NAME_2 "com.apple.testservice2"
146*a325d9c4SApple OSS Distributions #define SERVICE_DOMAIN_2 (2)
147*a325d9c4SApple OSS Distributions 
148*a325d9c4SApple OSS Distributions T_DECL(mach_fake_service_port, "Create a connection port with a fake service port", T_META_CHECK_LEAKS(false))
149*a325d9c4SApple OSS Distributions {
150*a325d9c4SApple OSS Distributions 	mach_port_t connection_port;
151*a325d9c4SApple OSS Distributions 	mach_port_t fake_service_port;
152*a325d9c4SApple OSS Distributions 	mach_port_t service_port_2;
153*a325d9c4SApple OSS Distributions 
154*a325d9c4SApple OSS Distributions 	kern_return_t kr;
155*a325d9c4SApple OSS Distributions 
156*a325d9c4SApple OSS Distributions 	struct mach_service_port_info sp_info = {};
157*a325d9c4SApple OSS Distributions 
158*a325d9c4SApple OSS Distributions 	strcpy(sp_info.mspi_string_name, SERVICE_NAME_2);
159*a325d9c4SApple OSS Distributions 	sp_info.mspi_domain_type = (uint8_t)SERVICE_DOMAIN_2;
160*a325d9c4SApple OSS Distributions 
161*a325d9c4SApple OSS Distributions 	mach_port_options_t opts = {
162*a325d9c4SApple OSS Distributions 		.flags = MPO_CONNECTION_PORT | MPO_SERVICE_PORT | MPO_INSERT_SEND_RIGHT | MPO_CONTEXT_AS_GUARD,
163*a325d9c4SApple OSS Distributions 		.service_port_info = &sp_info,
164*a325d9c4SApple OSS Distributions 	};
165*a325d9c4SApple OSS Distributions 
166*a325d9c4SApple OSS Distributions 	kr = mach_port_construct(mach_task_self(), &opts, SP_CONTEXT, &service_port_2);
167*a325d9c4SApple OSS Distributions 	T_ASSERT_MACH_ERROR(kr, KERN_INVALID_ARGUMENT, "mach_port_construct with extra flags %u", service_port_2);
168*a325d9c4SApple OSS Distributions 
169*a325d9c4SApple OSS Distributions 	mach_port_options_t opts2 = {
170*a325d9c4SApple OSS Distributions 		.flags = MPO_SERVICE_PORT | MPO_INSERT_SEND_RIGHT | MPO_CONTEXT_AS_GUARD,
171*a325d9c4SApple OSS Distributions 		.service_port_info = NULL,
172*a325d9c4SApple OSS Distributions 	};
173*a325d9c4SApple OSS Distributions 
174*a325d9c4SApple OSS Distributions 	kr = mach_port_construct(mach_task_self(), &opts2, SP_CONTEXT, &service_port_2);
175*a325d9c4SApple OSS Distributions 	T_ASSERT_MACH_ERROR(kr, KERN_INVALID_ARGUMENT, "mach_port_construct with missing service port info %u", service_port_2);
176*a325d9c4SApple OSS Distributions 
177*a325d9c4SApple OSS Distributions 	mach_port_options_t opts3 = {
178*a325d9c4SApple OSS Distributions 		.flags = MPO_INSERT_SEND_RIGHT | MPO_CONTEXT_AS_GUARD,
179*a325d9c4SApple OSS Distributions 	};
180*a325d9c4SApple OSS Distributions 
181*a325d9c4SApple OSS Distributions 	kr = mach_port_construct(mach_task_self(), &opts3, SP_CONTEXT, &fake_service_port);
182*a325d9c4SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_port_construct with missing flag %u", fake_service_port);
183*a325d9c4SApple OSS Distributions 
184*a325d9c4SApple OSS Distributions 	struct mach_service_port_info sp_info3 = {};
185*a325d9c4SApple OSS Distributions 	kr = mach_port_get_service_port_info(mach_task_self(), fake_service_port, &sp_info3);
186*a325d9c4SApple OSS Distributions 	T_ASSERT_MACH_ERROR(kr, KERN_INVALID_CAPABILITY, "mach_port_get_service_port_info");
187*a325d9c4SApple OSS Distributions 
188*a325d9c4SApple OSS Distributions 	mach_port_options_t opts4 = {
189*a325d9c4SApple OSS Distributions 		.flags = MPO_CONNECTION_PORT,
190*a325d9c4SApple OSS Distributions 		.service_port_name = fake_service_port,
191*a325d9c4SApple OSS Distributions 	};
192*a325d9c4SApple OSS Distributions 
193*a325d9c4SApple OSS Distributions 	kr = mach_port_construct(mach_task_self(), &opts4, 0x0, &connection_port);
194*a325d9c4SApple OSS Distributions 	T_ASSERT_MACH_ERROR(kr, KERN_INVALID_CAPABILITY, "mach_port_construct connection port %u", connection_port);
195*a325d9c4SApple OSS Distributions 
196*a325d9c4SApple OSS Distributions 	T_LOG("done");
197*a325d9c4SApple OSS Distributions }
198*a325d9c4SApple OSS Distributions 
199*a325d9c4SApple OSS Distributions T_DECL(mach_dead_service_port, "Create a connection port with a dead service port", T_META_CHECK_LEAKS(false))
200*a325d9c4SApple OSS Distributions {
201*a325d9c4SApple OSS Distributions 	mach_port_t connection_port;
202*a325d9c4SApple OSS Distributions 	mach_port_t service_port_2;
203*a325d9c4SApple OSS Distributions 
204*a325d9c4SApple OSS Distributions 	kern_return_t kr;
205*a325d9c4SApple OSS Distributions 
206*a325d9c4SApple OSS Distributions 	struct mach_service_port_info sp_info = {};
207*a325d9c4SApple OSS Distributions 
208*a325d9c4SApple OSS Distributions 	strcpy(sp_info.mspi_string_name, SERVICE_NAME_2);
209*a325d9c4SApple OSS Distributions 	sp_info.mspi_domain_type = (uint8_t)SERVICE_DOMAIN_2;
210*a325d9c4SApple OSS Distributions 
211*a325d9c4SApple OSS Distributions 	mach_port_options_t opts = {
212*a325d9c4SApple OSS Distributions 		.flags = MPO_SERVICE_PORT | MPO_INSERT_SEND_RIGHT,
213*a325d9c4SApple OSS Distributions 		.service_port_info = &sp_info,
214*a325d9c4SApple OSS Distributions 	};
215*a325d9c4SApple OSS Distributions 
216*a325d9c4SApple OSS Distributions 	kr = mach_port_construct(mach_task_self(), &opts, 0, &service_port_2);
217*a325d9c4SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_port_construct %u", service_port_2);
218*a325d9c4SApple OSS Distributions 
219*a325d9c4SApple OSS Distributions 	kr = mach_port_mod_refs(mach_task_self(), service_port_2, MACH_PORT_RIGHT_RECEIVE, -1);
220*a325d9c4SApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "mach_port_mod_refs");
221*a325d9c4SApple OSS Distributions 
222*a325d9c4SApple OSS Distributions 	mach_port_options_t opts3 = {
223*a325d9c4SApple OSS Distributions 		.flags = MPO_CONNECTION_PORT,
224*a325d9c4SApple OSS Distributions 		.service_port_name = service_port_2,
225*a325d9c4SApple OSS Distributions 	};
226*a325d9c4SApple OSS Distributions 
227*a325d9c4SApple OSS Distributions 	kr = mach_port_construct(mach_task_self(), &opts3, 0x0, &connection_port);
228*a325d9c4SApple OSS Distributions 	T_LOG("mach_port_construct connection port kr = %d", kr);
229*a325d9c4SApple OSS Distributions 
230*a325d9c4SApple OSS Distributions 	if (kr == KERN_INVALID_RIGHT || kr == KERN_INVALID_NAME) {
231*a325d9c4SApple OSS Distributions 		T_PASS("Invalid service port");
232*a325d9c4SApple OSS Distributions 	} else {
233*a325d9c4SApple OSS Distributions 		T_FAIL("mach_port_construct incorrect return value");
234*a325d9c4SApple OSS Distributions 	}
235*a325d9c4SApple OSS Distributions 
236*a325d9c4SApple OSS Distributions 	T_LOG("done");
237*a325d9c4SApple OSS Distributions }
238