1*a1e26a70SApple OSS Distributions #include <darwintest.h>
2*a1e26a70SApple OSS Distributions #include <servers/bootstrap.h>
3*a1e26a70SApple OSS Distributions #include <mach/mach.h>
4*a1e26a70SApple OSS Distributions #include <mach/message.h>
5*a1e26a70SApple OSS Distributions #include <stdlib.h>
6*a1e26a70SApple OSS Distributions #include <sys/sysctl.h>
7*a1e26a70SApple OSS Distributions #include <unistd.h>
8*a1e26a70SApple OSS Distributions
9*a1e26a70SApple OSS Distributions T_GLOBAL_META(
10*a1e26a70SApple OSS Distributions T_META_NAMESPACE("xnu.ipc"),
11*a1e26a70SApple OSS Distributions T_META_RUN_CONCURRENTLY(TRUE),
12*a1e26a70SApple OSS Distributions T_META_RADAR_COMPONENT_NAME("xnu"),
13*a1e26a70SApple OSS Distributions T_META_RADAR_COMPONENT_VERSION("IPC"),
14*a1e26a70SApple OSS Distributions T_META_TAG_VM_PREFERRED);
15*a1e26a70SApple OSS Distributions
16*a1e26a70SApple OSS Distributions typedef struct {
17*a1e26a70SApple OSS Distributions mach_msg_header_t header;
18*a1e26a70SApple OSS Distributions mach_msg_body_t body;
19*a1e26a70SApple OSS Distributions mach_msg_guarded_port_descriptor_t guarded_port_descriptor1;
20*a1e26a70SApple OSS Distributions mach_msg_guarded_port_descriptor_t guarded_port_descriptor2;
21*a1e26a70SApple OSS Distributions mach_msg_trailer_t trailer; // subtract this when sending
22*a1e26a70SApple OSS Distributions } ipc_complex_message;
23*a1e26a70SApple OSS Distributions
24*a1e26a70SApple OSS Distributions static ipc_complex_message icm_request = {};
25*a1e26a70SApple OSS Distributions
26*a1e26a70SApple OSS Distributions struct args {
27*a1e26a70SApple OSS Distributions const char *progname;
28*a1e26a70SApple OSS Distributions int verbose;
29*a1e26a70SApple OSS Distributions int voucher;
30*a1e26a70SApple OSS Distributions int num_msgs;
31*a1e26a70SApple OSS Distributions const char *server_port_name;
32*a1e26a70SApple OSS Distributions mach_port_t server_port;
33*a1e26a70SApple OSS Distributions mach_port_t reply_port;
34*a1e26a70SApple OSS Distributions mach_port_t voucher_port;
35*a1e26a70SApple OSS Distributions int request_msg_size;
36*a1e26a70SApple OSS Distributions void *request_msg;
37*a1e26a70SApple OSS Distributions int reply_msg_size;
38*a1e26a70SApple OSS Distributions void *reply_msg;
39*a1e26a70SApple OSS Distributions mach_port_t sp_voucher_port;
40*a1e26a70SApple OSS Distributions uint32_t persona_id;
41*a1e26a70SApple OSS Distributions long client_pid;
42*a1e26a70SApple OSS Distributions };
43*a1e26a70SApple OSS Distributions
44*a1e26a70SApple OSS Distributions void parse_args(struct args *args);
45*a1e26a70SApple OSS Distributions void* create_buffer(int *buffer_size);
46*a1e26a70SApple OSS Distributions void client(struct args *args);
47*a1e26a70SApple OSS Distributions void server_setup(struct args* args);
48*a1e26a70SApple OSS Distributions void server(struct args *args);
49*a1e26a70SApple OSS Distributions
50*a1e26a70SApple OSS Distributions void
parse_args(struct args * args)51*a1e26a70SApple OSS Distributions parse_args(struct args *args)
52*a1e26a70SApple OSS Distributions {
53*a1e26a70SApple OSS Distributions args->verbose = 0;
54*a1e26a70SApple OSS Distributions args->voucher = 0;
55*a1e26a70SApple OSS Distributions args->server_port_name = "TEST";
56*a1e26a70SApple OSS Distributions args->server_port = MACH_PORT_NULL;
57*a1e26a70SApple OSS Distributions args->reply_port = MACH_PORT_NULL;
58*a1e26a70SApple OSS Distributions args->voucher_port = MACH_PORT_NULL;
59*a1e26a70SApple OSS Distributions args->num_msgs = 1;
60*a1e26a70SApple OSS Distributions args->request_msg_size = sizeof(ipc_complex_message);
61*a1e26a70SApple OSS Distributions args->request_msg = &icm_request;
62*a1e26a70SApple OSS Distributions args->client_pid = getpid();
63*a1e26a70SApple OSS Distributions }
64*a1e26a70SApple OSS Distributions
65*a1e26a70SApple OSS Distributions /* Create a mach IPC listener which will respond to the client's message */
66*a1e26a70SApple OSS Distributions void
server_setup(struct args * args)67*a1e26a70SApple OSS Distributions server_setup(struct args* args)
68*a1e26a70SApple OSS Distributions {
69*a1e26a70SApple OSS Distributions kern_return_t ret;
70*a1e26a70SApple OSS Distributions mach_port_t bsport;
71*a1e26a70SApple OSS Distributions
72*a1e26a70SApple OSS Distributions ret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE,
73*a1e26a70SApple OSS Distributions &args->server_port);
74*a1e26a70SApple OSS Distributions T_ASSERT_MACH_SUCCESS(ret, "server: mach_port_allocate()");
75*a1e26a70SApple OSS Distributions
76*a1e26a70SApple OSS Distributions ret = mach_port_insert_right(mach_task_self(), args->server_port, args->server_port,
77*a1e26a70SApple OSS Distributions MACH_MSG_TYPE_MAKE_SEND);
78*a1e26a70SApple OSS Distributions T_ASSERT_MACH_SUCCESS(ret, "server: mach_port_insert_right()");
79*a1e26a70SApple OSS Distributions
80*a1e26a70SApple OSS Distributions ret = task_get_bootstrap_port(mach_task_self(), &bsport);
81*a1e26a70SApple OSS Distributions T_ASSERT_MACH_SUCCESS(ret, "server: task_get_bootstrap_port()");
82*a1e26a70SApple OSS Distributions
83*a1e26a70SApple OSS Distributions ret = bootstrap_register(bsport, args->server_port_name, args->server_port);
84*a1e26a70SApple OSS Distributions T_ASSERT_MACH_SUCCESS(ret, "server: bootstrap_register()");
85*a1e26a70SApple OSS Distributions
86*a1e26a70SApple OSS Distributions T_LOG("server: waiting for IPC messages from client on port '%s'.\n",
87*a1e26a70SApple OSS Distributions args->server_port_name);
88*a1e26a70SApple OSS Distributions }
89*a1e26a70SApple OSS Distributions
90*a1e26a70SApple OSS Distributions /* Server process loop
91*a1e26a70SApple OSS Distributions *
92*a1e26a70SApple OSS Distributions * Listens for message.
93*a1e26a70SApple OSS Distributions *
94*a1e26a70SApple OSS Distributions */
95*a1e26a70SApple OSS Distributions void
server(struct args * args)96*a1e26a70SApple OSS Distributions server(struct args *args)
97*a1e26a70SApple OSS Distributions {
98*a1e26a70SApple OSS Distributions mach_msg_header_t *request;
99*a1e26a70SApple OSS Distributions mach_msg_option_t rcvoption;
100*a1e26a70SApple OSS Distributions kern_return_t ret;
101*a1e26a70SApple OSS Distributions
102*a1e26a70SApple OSS Distributions request = (mach_msg_header_t *)args->request_msg;
103*a1e26a70SApple OSS Distributions
104*a1e26a70SApple OSS Distributions rcvoption = MACH_RCV_MSG | MACH_RCV_INTERRUPT | MACH_RCV_GUARDED_DESC;
105*a1e26a70SApple OSS Distributions
106*a1e26a70SApple OSS Distributions T_LOG("server: Awaiting message\n");
107*a1e26a70SApple OSS Distributions ret = mach_msg(request,
108*a1e26a70SApple OSS Distributions rcvoption,
109*a1e26a70SApple OSS Distributions 0,
110*a1e26a70SApple OSS Distributions sizeof(ipc_complex_message),
111*a1e26a70SApple OSS Distributions args->server_port,
112*a1e26a70SApple OSS Distributions MACH_MSG_TIMEOUT_NONE,
113*a1e26a70SApple OSS Distributions MACH_PORT_NULL);
114*a1e26a70SApple OSS Distributions
115*a1e26a70SApple OSS Distributions T_ASSERT_MACH_SUCCESS(ret, "server: mach_msg receive");
116*a1e26a70SApple OSS Distributions
117*a1e26a70SApple OSS Distributions ipc_complex_message *request_complexmsg = (ipc_complex_message *)request;
118*a1e26a70SApple OSS Distributions T_ASSERT_NE(request_complexmsg->guarded_port_descriptor1.name, 0, "server: Should not receive mach_port_null; name = %x", request_complexmsg->guarded_port_descriptor1.name);
119*a1e26a70SApple OSS Distributions T_ASSERT_EQ((mach_msg_descriptor_type_t)request_complexmsg->guarded_port_descriptor1.type, MACH_MSG_GUARDED_PORT_DESCRIPTOR, "server: Received a guarded port descriptor");
120*a1e26a70SApple OSS Distributions T_ASSERT_EQ((mach_msg_type_name_t)request_complexmsg->guarded_port_descriptor1.disposition, MACH_MSG_TYPE_PORT_RECEIVE, "server: Received a receive right");
121*a1e26a70SApple OSS Distributions T_ASSERT_EQ(request_complexmsg->guarded_port_descriptor1.context, (unsigned long)request, "server: Received a port with correct context = %p", request);
122*a1e26a70SApple OSS Distributions T_LOG("Guard flags = %d", request_complexmsg->guarded_port_descriptor1.flags);
123*a1e26a70SApple OSS Distributions
124*a1e26a70SApple OSS Distributions T_ASSERT_NE(request_complexmsg->guarded_port_descriptor2.name, 0, "server: Should not receive mach_port_null; name = %x", request_complexmsg->guarded_port_descriptor2.name);
125*a1e26a70SApple OSS Distributions T_ASSERT_EQ((mach_msg_descriptor_type_t)request_complexmsg->guarded_port_descriptor2.type, MACH_MSG_GUARDED_PORT_DESCRIPTOR, "server: Received a guarded port descriptor");
126*a1e26a70SApple OSS Distributions T_ASSERT_EQ((mach_msg_type_name_t)request_complexmsg->guarded_port_descriptor2.disposition, MACH_MSG_TYPE_PORT_RECEIVE, "server: Received a receive right");
127*a1e26a70SApple OSS Distributions T_ASSERT_EQ(request_complexmsg->guarded_port_descriptor2.context, (unsigned long)request, "server: Received a port with correct context = %p", request);
128*a1e26a70SApple OSS Distributions
129*a1e26a70SApple OSS Distributions mach_port_status_t status;
130*a1e26a70SApple OSS Distributions mach_msg_type_number_t status_size = MACH_PORT_RECEIVE_STATUS_COUNT;
131*a1e26a70SApple OSS Distributions
132*a1e26a70SApple OSS Distributions kern_return_t kr = mach_port_get_attributes(mach_task_self(), request_complexmsg->guarded_port_descriptor1.name,
133*a1e26a70SApple OSS Distributions MACH_PORT_RECEIVE_STATUS, (mach_port_info_t)&status, &status_size);
134*a1e26a70SApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "mach_port_get_attributes for descriptor 1");
135*a1e26a70SApple OSS Distributions T_LOG("Status flags %d", status.mps_flags);
136*a1e26a70SApple OSS Distributions T_ASSERT_NE(0, (status.mps_flags & MACH_PORT_STATUS_FLAG_GUARD_IMMOVABLE_RECEIVE), "Imm rcv bit is set for descriptor1");
137*a1e26a70SApple OSS Distributions
138*a1e26a70SApple OSS Distributions kr = mach_port_get_attributes(mach_task_self(), request_complexmsg->guarded_port_descriptor2.name,
139*a1e26a70SApple OSS Distributions MACH_PORT_RECEIVE_STATUS, (mach_port_info_t)&status, &status_size);
140*a1e26a70SApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "mach_port_get_attributes for descriptor 2");
141*a1e26a70SApple OSS Distributions T_LOG("Status flags %d", status.mps_flags);
142*a1e26a70SApple OSS Distributions T_ASSERT_NE(0, (status.mps_flags & MACH_PORT_STATUS_FLAG_GUARD_IMMOVABLE_RECEIVE), "Imm rcv bit is set for descriptor2");
143*a1e26a70SApple OSS Distributions
144*a1e26a70SApple OSS Distributions mach_msg_destroy(request);
145*a1e26a70SApple OSS Distributions }
146*a1e26a70SApple OSS Distributions
147*a1e26a70SApple OSS Distributions void
client(struct args * args)148*a1e26a70SApple OSS Distributions client(struct args *args)
149*a1e26a70SApple OSS Distributions {
150*a1e26a70SApple OSS Distributions //Find the bootstrap port
151*a1e26a70SApple OSS Distributions mach_port_t bsport;
152*a1e26a70SApple OSS Distributions mach_port_t guarded_port;
153*a1e26a70SApple OSS Distributions mach_port_t unguarded_port;
154*a1e26a70SApple OSS Distributions
155*a1e26a70SApple OSS Distributions kern_return_t ret = task_get_bootstrap_port(mach_task_self(), &bsport);
156*a1e26a70SApple OSS Distributions T_ASSERT_MACH_SUCCESS(ret, "client: task_get_bootstrap_port()");
157*a1e26a70SApple OSS Distributions
158*a1e26a70SApple OSS Distributions //Look up the service port
159*a1e26a70SApple OSS Distributions ret = bootstrap_look_up(bsport, (char *)args->server_port_name,
160*a1e26a70SApple OSS Distributions &args->server_port);
161*a1e26a70SApple OSS Distributions T_ASSERT_MACH_SUCCESS(ret, "client: bootstrap_look_up()");
162*a1e26a70SApple OSS Distributions
163*a1e26a70SApple OSS Distributions //Create the unguarded port
164*a1e26a70SApple OSS Distributions ret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE,
165*a1e26a70SApple OSS Distributions &unguarded_port);
166*a1e26a70SApple OSS Distributions T_ASSERT_MACH_SUCCESS(ret, "client: mach_port_allocate() reply port");
167*a1e26a70SApple OSS Distributions
168*a1e26a70SApple OSS Distributions mach_port_options_t opts = {
169*a1e26a70SApple OSS Distributions .flags = MPO_CONTEXT_AS_GUARD
170*a1e26a70SApple OSS Distributions };
171*a1e26a70SApple OSS Distributions
172*a1e26a70SApple OSS Distributions ret = mach_port_construct(mach_task_self(), &opts, 0x10, &guarded_port);
173*a1e26a70SApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(ret, "mach_port_construct");
174*a1e26a70SApple OSS Distributions
175*a1e26a70SApple OSS Distributions //Construct the message
176*a1e26a70SApple OSS Distributions mach_msg_header_t *request = (mach_msg_header_t *)args->request_msg;
177*a1e26a70SApple OSS Distributions request->msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE,
178*a1e26a70SApple OSS Distributions 0, 0) | MACH_MSGH_BITS_COMPLEX;
179*a1e26a70SApple OSS Distributions request->msgh_size = (mach_msg_size_t)args->request_msg_size;
180*a1e26a70SApple OSS Distributions request->msgh_remote_port = args->server_port;
181*a1e26a70SApple OSS Distributions request->msgh_local_port = args->reply_port;
182*a1e26a70SApple OSS Distributions request->msgh_id = 1;
183*a1e26a70SApple OSS Distributions
184*a1e26a70SApple OSS Distributions ipc_complex_message *complexmsg = (ipc_complex_message *)request;
185*a1e26a70SApple OSS Distributions complexmsg->body.msgh_descriptor_count = 2;
186*a1e26a70SApple OSS Distributions complexmsg->guarded_port_descriptor1.name = guarded_port;
187*a1e26a70SApple OSS Distributions complexmsg->guarded_port_descriptor1.disposition = MACH_MSG_TYPE_MOVE_RECEIVE;
188*a1e26a70SApple OSS Distributions complexmsg->guarded_port_descriptor1.flags = MACH_MSG_GUARD_FLAGS_IMMOVABLE_RECEIVE;
189*a1e26a70SApple OSS Distributions complexmsg->guarded_port_descriptor1.context = 0x10;
190*a1e26a70SApple OSS Distributions complexmsg->guarded_port_descriptor1.type = MACH_MSG_GUARDED_PORT_DESCRIPTOR;
191*a1e26a70SApple OSS Distributions
192*a1e26a70SApple OSS Distributions complexmsg->guarded_port_descriptor2.name = unguarded_port;
193*a1e26a70SApple OSS Distributions complexmsg->guarded_port_descriptor2.disposition = MACH_MSG_TYPE_MOVE_RECEIVE;
194*a1e26a70SApple OSS Distributions complexmsg->guarded_port_descriptor2.flags = MACH_MSG_GUARD_FLAGS_IMMOVABLE_RECEIVE | MACH_MSG_GUARD_FLAGS_UNGUARDED_ON_SEND;
195*a1e26a70SApple OSS Distributions complexmsg->guarded_port_descriptor2.context = 0;
196*a1e26a70SApple OSS Distributions complexmsg->guarded_port_descriptor2.type = MACH_MSG_GUARDED_PORT_DESCRIPTOR;
197*a1e26a70SApple OSS Distributions
198*a1e26a70SApple OSS Distributions mach_msg_option_t option = MACH_SEND_MSG;
199*a1e26a70SApple OSS Distributions
200*a1e26a70SApple OSS Distributions //Listen for the reply on the reply port
201*a1e26a70SApple OSS Distributions T_LOG("client: Sending request\n");
202*a1e26a70SApple OSS Distributions ret = mach_msg(request,
203*a1e26a70SApple OSS Distributions option,
204*a1e26a70SApple OSS Distributions (mach_msg_size_t)args->request_msg_size,
205*a1e26a70SApple OSS Distributions 0,
206*a1e26a70SApple OSS Distributions MACH_PORT_NULL,
207*a1e26a70SApple OSS Distributions MACH_MSG_TIMEOUT_NONE,
208*a1e26a70SApple OSS Distributions MACH_PORT_NULL);
209*a1e26a70SApple OSS Distributions T_ASSERT_MACH_SUCCESS(ret, "client: mach_msg_overwrite()");
210*a1e26a70SApple OSS Distributions }
211*a1e26a70SApple OSS Distributions
212*a1e26a70SApple OSS Distributions T_DECL(mo_immovable_receive, "Send a message containing a guard port descriptor for an immovable receive right")
213*a1e26a70SApple OSS Distributions {
214*a1e26a70SApple OSS Distributions struct args args = {};
215*a1e26a70SApple OSS Distributions parse_args(&args);
216*a1e26a70SApple OSS Distributions args.request_msg_size -= sizeof(mach_msg_trailer_t);
217*a1e26a70SApple OSS Distributions args.reply_msg_size -= sizeof(mach_msg_trailer_t);
218*a1e26a70SApple OSS Distributions
219*a1e26a70SApple OSS Distributions //Create the server
220*a1e26a70SApple OSS Distributions pid_t pid = fork();
221*a1e26a70SApple OSS Distributions if (pid == 0) {
222*a1e26a70SApple OSS Distributions T_LOG("Server is up");
223*a1e26a70SApple OSS Distributions server_setup(&args);
224*a1e26a70SApple OSS Distributions server(&args);
225*a1e26a70SApple OSS Distributions exit(0);
226*a1e26a70SApple OSS Distributions }
227*a1e26a70SApple OSS Distributions
228*a1e26a70SApple OSS Distributions sleep(2);
229*a1e26a70SApple OSS Distributions T_LOG("Preparing client to send a request");
230*a1e26a70SApple OSS Distributions client(&args);
231*a1e26a70SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(waitpid(pid, NULL, 0), "waitpid()");
232*a1e26a70SApple OSS Distributions }
233