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