xref: /xnu-11215.1.10/tests/ipc_mach_port.c (revision 8d741a5de7ff4191bf97d57b9f54c2f6d4a15585)
1*8d741a5dSApple OSS Distributions #include <darwintest.h>
2*8d741a5dSApple OSS Distributions #include <darwintest_multiprocess.h>
3*8d741a5dSApple OSS Distributions #include <launch.h>
4*8d741a5dSApple OSS Distributions #include <servers/bootstrap.h>
5*8d741a5dSApple OSS Distributions #include <sys/sysctl.h>
6*8d741a5dSApple OSS Distributions #include "exc_helpers.h"
7*8d741a5dSApple OSS Distributions 
8*8d741a5dSApple OSS Distributions T_GLOBAL_META(
9*8d741a5dSApple OSS Distributions 	T_META_NAMESPACE("xnu.ipc"),
10*8d741a5dSApple OSS Distributions 	T_META_RADAR_COMPONENT_NAME("xnu"),
11*8d741a5dSApple OSS Distributions 	T_META_RADAR_COMPONENT_VERSION("IPC"),
12*8d741a5dSApple OSS Distributions 	T_META_RUN_CONCURRENTLY(true),
13*8d741a5dSApple OSS Distributions 	T_META_TAG_VM_PREFERRED);
14*8d741a5dSApple OSS Distributions 
15*8d741a5dSApple OSS Distributions #pragma mark - helpers
16*8d741a5dSApple OSS Distributions 
17*8d741a5dSApple OSS Distributions #define SERVICE_NAME  "com.apple.xnu.test.mach_port"
18*8d741a5dSApple OSS Distributions 
19*8d741a5dSApple OSS Distributions struct one_port_msg {
20*8d741a5dSApple OSS Distributions 	mach_msg_header_t          header;
21*8d741a5dSApple OSS Distributions 	mach_msg_body_t            body;
22*8d741a5dSApple OSS Distributions 	mach_msg_port_descriptor_t port_descriptor;
23*8d741a5dSApple OSS Distributions 	mach_msg_trailer_t         trailer;            // subtract this when sending
24*8d741a5dSApple OSS Distributions };
25*8d741a5dSApple OSS Distributions 
26*8d741a5dSApple OSS Distributions static mach_port_t
server_checkin(void)27*8d741a5dSApple OSS Distributions server_checkin(void)
28*8d741a5dSApple OSS Distributions {
29*8d741a5dSApple OSS Distributions 	mach_port_t mp;
30*8d741a5dSApple OSS Distributions 	kern_return_t kr;
31*8d741a5dSApple OSS Distributions 
32*8d741a5dSApple OSS Distributions 	kr = bootstrap_check_in(bootstrap_port, SERVICE_NAME, &mp);
33*8d741a5dSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "bootstrap_check_in");
34*8d741a5dSApple OSS Distributions 	return mp;
35*8d741a5dSApple OSS Distributions }
36*8d741a5dSApple OSS Distributions 
37*8d741a5dSApple OSS Distributions static mach_port_t
server_lookup(void)38*8d741a5dSApple OSS Distributions server_lookup(void)
39*8d741a5dSApple OSS Distributions {
40*8d741a5dSApple OSS Distributions 	mach_port_t mp;
41*8d741a5dSApple OSS Distributions 	kern_return_t kr;
42*8d741a5dSApple OSS Distributions 
43*8d741a5dSApple OSS Distributions 	kr = bootstrap_look_up(bootstrap_port, SERVICE_NAME, &mp);
44*8d741a5dSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "bootstrap_look_up");
45*8d741a5dSApple OSS Distributions 	return mp;
46*8d741a5dSApple OSS Distributions }
47*8d741a5dSApple OSS Distributions 
48*8d741a5dSApple OSS Distributions static mach_port_t
make_sr_port(void)49*8d741a5dSApple OSS Distributions make_sr_port(void)
50*8d741a5dSApple OSS Distributions {
51*8d741a5dSApple OSS Distributions 	mach_port_options_t opts = {
52*8d741a5dSApple OSS Distributions 		.flags = MPO_INSERT_SEND_RIGHT,
53*8d741a5dSApple OSS Distributions 	};
54*8d741a5dSApple OSS Distributions 	kern_return_t kr;
55*8d741a5dSApple OSS Distributions 	mach_port_t port;
56*8d741a5dSApple OSS Distributions 
57*8d741a5dSApple OSS Distributions 	kr = mach_port_construct(mach_task_self(), &opts, 0ull, &port);
58*8d741a5dSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "mach_port_construct");
59*8d741a5dSApple OSS Distributions 	return port;
60*8d741a5dSApple OSS Distributions }
61*8d741a5dSApple OSS Distributions 
62*8d741a5dSApple OSS Distributions static void
destroy_port(mach_port_t port,bool receive,int srights)63*8d741a5dSApple OSS Distributions destroy_port(mach_port_t port, bool receive, int srights)
64*8d741a5dSApple OSS Distributions {
65*8d741a5dSApple OSS Distributions 	kern_return_t kr;
66*8d741a5dSApple OSS Distributions 
67*8d741a5dSApple OSS Distributions 	if (srights) {
68*8d741a5dSApple OSS Distributions 		kr = mach_port_mod_refs(mach_task_self(), port,
69*8d741a5dSApple OSS Distributions 		    MACH_PORT_RIGHT_SEND, -srights);
70*8d741a5dSApple OSS Distributions 		T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "srights -= %d", srights);
71*8d741a5dSApple OSS Distributions 	}
72*8d741a5dSApple OSS Distributions 	if (receive) {
73*8d741a5dSApple OSS Distributions 		kr = mach_port_mod_refs(mach_task_self(), port,
74*8d741a5dSApple OSS Distributions 		    MACH_PORT_RIGHT_RECEIVE, -1);
75*8d741a5dSApple OSS Distributions 		T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "receive -= 1");
76*8d741a5dSApple OSS Distributions 	}
77*8d741a5dSApple OSS Distributions }
78*8d741a5dSApple OSS Distributions 
79*8d741a5dSApple OSS Distributions static void
send_port(mach_msg_id_t id,mach_port_t dest,mach_port_t right,mach_msg_type_name_t disp)80*8d741a5dSApple OSS Distributions send_port(
81*8d741a5dSApple OSS Distributions 	mach_msg_id_t        id,
82*8d741a5dSApple OSS Distributions 	mach_port_t          dest,
83*8d741a5dSApple OSS Distributions 	mach_port_t          right,
84*8d741a5dSApple OSS Distributions 	mach_msg_type_name_t disp)
85*8d741a5dSApple OSS Distributions {
86*8d741a5dSApple OSS Distributions 	struct one_port_msg msg = {
87*8d741a5dSApple OSS Distributions 		.header = {
88*8d741a5dSApple OSS Distributions 			.msgh_remote_port = dest,
89*8d741a5dSApple OSS Distributions 			.msgh_bits        = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_COPY_SEND,
90*8d741a5dSApple OSS Distributions 	    0, MACH_MSG_TYPE_MOVE_SEND, MACH_MSGH_BITS_COMPLEX),
91*8d741a5dSApple OSS Distributions 			.msgh_id          = id,
92*8d741a5dSApple OSS Distributions 			.msgh_size        = offsetof(struct one_port_msg, trailer),
93*8d741a5dSApple OSS Distributions 		},
94*8d741a5dSApple OSS Distributions 		.body = {
95*8d741a5dSApple OSS Distributions 			.msgh_descriptor_count = 1,
96*8d741a5dSApple OSS Distributions 		},
97*8d741a5dSApple OSS Distributions 		.port_descriptor = {
98*8d741a5dSApple OSS Distributions 			.name        = right,
99*8d741a5dSApple OSS Distributions 			.disposition = disp,
100*8d741a5dSApple OSS Distributions 			.type        = MACH_MSG_PORT_DESCRIPTOR,
101*8d741a5dSApple OSS Distributions 		},
102*8d741a5dSApple OSS Distributions 	};
103*8d741a5dSApple OSS Distributions 	kern_return_t kr;
104*8d741a5dSApple OSS Distributions 
105*8d741a5dSApple OSS Distributions 	kr = mach_msg(&msg.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT,
106*8d741a5dSApple OSS Distributions 	    msg.header.msgh_size, 0, MACH_PORT_NULL, 10000, 0);
107*8d741a5dSApple OSS Distributions 
108*8d741a5dSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "send(%d)", id);
109*8d741a5dSApple OSS Distributions }
110*8d741a5dSApple OSS Distributions 
111*8d741a5dSApple OSS Distributions #pragma mark - basic test about right deduplication
112*8d741a5dSApple OSS Distributions 
113*8d741a5dSApple OSS Distributions static mach_port_t
receive_port(mach_msg_id_t expected_id,mach_port_t rcv_port,mach_msg_type_name_t expected_disp)114*8d741a5dSApple OSS Distributions receive_port(
115*8d741a5dSApple OSS Distributions 	mach_msg_id_t        expected_id,
116*8d741a5dSApple OSS Distributions 	mach_port_t          rcv_port,
117*8d741a5dSApple OSS Distributions 	mach_msg_type_name_t expected_disp)
118*8d741a5dSApple OSS Distributions {
119*8d741a5dSApple OSS Distributions 	struct one_port_msg msg = { };
120*8d741a5dSApple OSS Distributions 	kern_return_t kr;
121*8d741a5dSApple OSS Distributions 
122*8d741a5dSApple OSS Distributions 	T_LOG("waiting for message %d", expected_id);
123*8d741a5dSApple OSS Distributions 	kr = mach_msg(&msg.header, MACH_RCV_MSG, 0,
124*8d741a5dSApple OSS Distributions 	    sizeof(msg), rcv_port, 0, 0);
125*8d741a5dSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "receive(%d)", expected_id);
126*8d741a5dSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(msg.header.msgh_id, expected_id, "message id matches");
127*8d741a5dSApple OSS Distributions 	T_QUIET; T_ASSERT_NE(msg.header.msgh_bits & MACH_MSGH_BITS_COMPLEX, 0,
128*8d741a5dSApple OSS Distributions 	    "message is complex");
129*8d741a5dSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(msg.body.msgh_descriptor_count, 1, "message has one right");
130*8d741a5dSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ((mach_msg_type_name_t)msg.port_descriptor.disposition, expected_disp,
131*8d741a5dSApple OSS Distributions 	    "port has right disposition");
132*8d741a5dSApple OSS Distributions 	return msg.port_descriptor.name;
133*8d741a5dSApple OSS Distributions }
134*8d741a5dSApple OSS Distributions 
135*8d741a5dSApple OSS Distributions T_HELPER_DECL(right_dedup_server, "right_dedup_server")
136*8d741a5dSApple OSS Distributions {
137*8d741a5dSApple OSS Distributions 	mach_port_t svc_port = server_checkin();
138*8d741a5dSApple OSS Distributions 	mach_port_t ports[3];
139*8d741a5dSApple OSS Distributions 
140*8d741a5dSApple OSS Distributions 	ports[0] = receive_port(1, svc_port, MACH_MSG_TYPE_MOVE_RECEIVE);
141*8d741a5dSApple OSS Distributions 	ports[1] = receive_port(2, svc_port, MACH_MSG_TYPE_MOVE_SEND);
142*8d741a5dSApple OSS Distributions 	ports[2] = receive_port(3, svc_port, MACH_MSG_TYPE_MOVE_SEND);
143*8d741a5dSApple OSS Distributions 	T_ASSERT_EQ(ports[0], ports[1], "receive, send, send");
144*8d741a5dSApple OSS Distributions 	T_ASSERT_EQ(ports[0], ports[2], "receive, send, send");
145*8d741a5dSApple OSS Distributions 	destroy_port(ports[0], true, 2);
146*8d741a5dSApple OSS Distributions 
147*8d741a5dSApple OSS Distributions 	ports[0] = receive_port(4, svc_port, MACH_MSG_TYPE_MOVE_SEND);
148*8d741a5dSApple OSS Distributions 	ports[1] = receive_port(5, svc_port, MACH_MSG_TYPE_MOVE_RECEIVE);
149*8d741a5dSApple OSS Distributions 	ports[2] = receive_port(6, svc_port, MACH_MSG_TYPE_MOVE_SEND);
150*8d741a5dSApple OSS Distributions 	T_ASSERT_EQ(ports[0], ports[1], "send, receive, send");
151*8d741a5dSApple OSS Distributions 	T_ASSERT_EQ(ports[0], ports[2], "send, receive, send");
152*8d741a5dSApple OSS Distributions 	destroy_port(ports[0], true, 2);
153*8d741a5dSApple OSS Distributions 
154*8d741a5dSApple OSS Distributions 	ports[0] = receive_port(7, svc_port, MACH_MSG_TYPE_MOVE_SEND);
155*8d741a5dSApple OSS Distributions 	ports[1] = receive_port(8, svc_port, MACH_MSG_TYPE_MOVE_SEND);
156*8d741a5dSApple OSS Distributions 	ports[2] = receive_port(9, svc_port, MACH_MSG_TYPE_MOVE_RECEIVE);
157*8d741a5dSApple OSS Distributions 	T_ASSERT_EQ(ports[0], ports[1], "send, send, receive");
158*8d741a5dSApple OSS Distributions 	T_ASSERT_EQ(ports[0], ports[2], "send, send, receive");
159*8d741a5dSApple OSS Distributions 	destroy_port(ports[0], true, 2);
160*8d741a5dSApple OSS Distributions 
161*8d741a5dSApple OSS Distributions 	T_END;
162*8d741a5dSApple OSS Distributions }
163*8d741a5dSApple OSS Distributions 
164*8d741a5dSApple OSS Distributions T_HELPER_DECL(right_dedup_client, "right_dedup_client")
165*8d741a5dSApple OSS Distributions {
166*8d741a5dSApple OSS Distributions 	mach_port_t svc_port = server_lookup();
167*8d741a5dSApple OSS Distributions 	mach_port_t port;
168*8d741a5dSApple OSS Distributions 
169*8d741a5dSApple OSS Distributions 	port = make_sr_port();
170*8d741a5dSApple OSS Distributions 	send_port(1, svc_port, port, MACH_MSG_TYPE_MOVE_RECEIVE);
171*8d741a5dSApple OSS Distributions 	send_port(2, svc_port, port, MACH_MSG_TYPE_COPY_SEND);
172*8d741a5dSApple OSS Distributions 	send_port(3, svc_port, port, MACH_MSG_TYPE_MOVE_SEND);
173*8d741a5dSApple OSS Distributions 
174*8d741a5dSApple OSS Distributions 	port = make_sr_port();
175*8d741a5dSApple OSS Distributions 	send_port(4, svc_port, port, MACH_MSG_TYPE_COPY_SEND);
176*8d741a5dSApple OSS Distributions 	send_port(5, svc_port, port, MACH_MSG_TYPE_MOVE_RECEIVE);
177*8d741a5dSApple OSS Distributions 	send_port(6, svc_port, port, MACH_MSG_TYPE_MOVE_SEND);
178*8d741a5dSApple OSS Distributions 
179*8d741a5dSApple OSS Distributions 	port = make_sr_port();
180*8d741a5dSApple OSS Distributions 	send_port(7, svc_port, port, MACH_MSG_TYPE_COPY_SEND);
181*8d741a5dSApple OSS Distributions 	send_port(8, svc_port, port, MACH_MSG_TYPE_MOVE_SEND);
182*8d741a5dSApple OSS Distributions 	send_port(9, svc_port, port, MACH_MSG_TYPE_MOVE_RECEIVE);
183*8d741a5dSApple OSS Distributions }
184*8d741a5dSApple OSS Distributions 
185*8d741a5dSApple OSS Distributions T_DECL(right_dedup, "make sure right deduplication works")
186*8d741a5dSApple OSS Distributions {
187*8d741a5dSApple OSS Distributions 	dt_helper_t helpers[] = {
188*8d741a5dSApple OSS Distributions 		dt_launchd_helper_domain("com.apple.xnu.test.mach_port.plist",
189*8d741a5dSApple OSS Distributions 	    "right_dedup_server", NULL, LAUNCH_SYSTEM_DOMAIN),
190*8d741a5dSApple OSS Distributions 		dt_fork_helper("right_dedup_client"),
191*8d741a5dSApple OSS Distributions 	};
192*8d741a5dSApple OSS Distributions 	dt_run_helpers(helpers, 2, 600);
193*8d741a5dSApple OSS Distributions }
194