1 #include <darwintest.h>
2 #include <servers/bootstrap.h>
4 #include <mach/message.h>
6 #include <sys/sysctl.h>
8 #include <darwintest_multiprocess.h>
9 #include <IOKit/IOKitLib.h>
12 mach_msg_header_t header
;
14 mach_msg_port_descriptor_t port_descriptor
;
15 mach_msg_trailer_t trailer
; // subtract this when sending
16 } ipc_complex_message
;
18 static ipc_complex_message icm_request
= {};
25 const char *server_port_name
;
26 mach_port_t server_port
;
27 mach_port_t reply_port
;
28 mach_port_t voucher_port
;
33 mach_port_t sp_voucher_port
;
39 parse_args(struct args
*args
)
43 args
->server_port_name
= "TEST_IMMOVABLE_SEND";
44 args
->server_port
= MACH_PORT_NULL
;
45 args
->reply_port
= MACH_PORT_NULL
;
46 args
->voucher_port
= MACH_PORT_NULL
;
48 args
->request_msg_size
= sizeof(ipc_complex_message
) - sizeof(mach_msg_trailer_t
);
49 //args->reply_msg_size = sizeof(ipc_complex_message2) - sizeof(mach_msg_trailer_t);
50 args
->request_msg
= &icm_request
;
51 args
->reply_msg
= NULL
;
52 args
->client_pid
= getpid();
58 struct args client_args
= {};
59 parse_args(&client_args
);
61 /* Find the bootstrap port */
63 kern_return_t ret
= task_get_bootstrap_port(mach_task_self(), &bsport
);
65 mach_error("client: task_get_bootstrap_port()", ret
);
69 printf("client: Look up bootstrap service port\n");
70 ret
= bootstrap_look_up(bsport
, client_args
.server_port_name
,
71 &client_args
.server_port
);
73 mach_error("client: bootstrap_look_up()", ret
);
77 printf("client: Look up the ioconnect service port to be sent\n");
78 io_service_t amfi
= IO_OBJECT_NULL
;
79 io_connect_t connect
= IO_OBJECT_NULL
;
82 amfi
= IOServiceGetMatchingService(kIOMasterPortDefault
, IOServiceMatching("AppleMobileFileIntegrity"));
83 if (amfi
== IO_OBJECT_NULL
) {
84 fprintf(stderr
, "client: unable to find AppleMobileFileIntegrity service\n");
87 ioret
= IOServiceOpen(amfi
, mach_task_self(), 0, &connect
);
88 if (ioret
!= kIOReturnSuccess
) {
89 fprintf(stderr
, "client: unable to open user client: 0x%x\n", ret
);
93 printf("client: Found the matching io_connect port = %d\n", connect
);
95 /* Construct the message */
96 mach_msg_header_t
*request
= (mach_msg_header_t
*)client_args
.request_msg
;
97 request
->msgh_bits
= MACH_MSGH_BITS_SET(MACH_MSG_TYPE_COPY_SEND
, 0,
98 0, 0) | MACH_MSGH_BITS_COMPLEX
;
99 request
->msgh_size
= (mach_msg_size_t
)client_args
.request_msg_size
;
100 request
->msgh_remote_port
= client_args
.server_port
;
101 request
->msgh_local_port
= MACH_PORT_NULL
;
102 request
->msgh_id
= 1;
104 ipc_complex_message
*complexmsg
= (ipc_complex_message
*)request
;
105 complexmsg
->body
.msgh_descriptor_count
= 1;
106 complexmsg
->port_descriptor
.name
= connect
;
107 complexmsg
->port_descriptor
.disposition
= MACH_MSG_TYPE_MOVE_SEND
;
108 complexmsg
->port_descriptor
.type
= MACH_MSG_PORT_DESCRIPTOR
;
110 mach_msg_option_t option
= MACH_SEND_MSG
;
112 printf("client: Sending request (expecting it to fail) \n");
113 mach_msg_return_t mret
= mach_msg(request
,
115 (mach_msg_size_t
)client_args
.request_msg_size
,
118 MACH_MSG_TIMEOUT_NONE
,
121 printf("client: mach_msg returned %x\n", mret
);
122 if (mret
!= MACH_SEND_INVALID_RIGHT
) {
123 mach_error("client: mach_msg", mret
);
127 printf("It should never reach here\n");