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