]>
Commit | Line | Data |
---|---|---|
1 | #include <darwintest.h> | |
2 | #include <servers/bootstrap.h> | |
3 | #include <mach/mach.h> | |
4 | #include <mach/message.h> | |
5 | #include <stdlib.h> | |
6 | #include <sys/sysctl.h> | |
7 | #include <unistd.h> | |
8 | #include <darwintest_multiprocess.h> | |
9 | #include <IOKit/IOKitLib.h> | |
10 | ||
11 | typedef struct { | |
12 | mach_msg_header_t header; | |
13 | mach_msg_body_t body; | |
14 | mach_msg_port_descriptor_t port_descriptor; | |
15 | mach_msg_trailer_t trailer; // subtract this when sending | |
16 | } ipc_complex_message; | |
17 | ||
18 | static ipc_complex_message icm_request = {}; | |
19 | ||
20 | struct args { | |
21 | const char *progname; | |
22 | int verbose; | |
23 | int voucher; | |
24 | int num_msgs; | |
25 | const char *server_port_name; | |
26 | mach_port_t server_port; | |
27 | mach_port_t reply_port; | |
28 | mach_port_t voucher_port; | |
29 | int request_msg_size; | |
30 | void *request_msg; | |
31 | int reply_msg_size; | |
32 | void *reply_msg; | |
33 | mach_port_t sp_voucher_port; | |
34 | uint32_t persona_id; | |
35 | long client_pid; | |
36 | }; | |
37 | ||
38 | static void | |
39 | parse_args(struct args *args) | |
40 | { | |
41 | args->verbose = 0; | |
42 | args->voucher = 0; | |
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; | |
47 | args->num_msgs = 1; | |
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(); | |
53 | } | |
54 | ||
55 | int | |
56 | main() | |
57 | { | |
58 | struct args client_args = {}; | |
59 | parse_args(&client_args); | |
60 | ||
61 | /* Find the bootstrap port */ | |
62 | mach_port_t bsport; | |
63 | kern_return_t ret = task_get_bootstrap_port(mach_task_self(), &bsport); | |
64 | if (ret) { | |
65 | mach_error("client: task_get_bootstrap_port()", ret); | |
66 | exit(1); | |
67 | } | |
68 | ||
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); | |
72 | if (ret) { | |
73 | mach_error("client: bootstrap_look_up()", ret); | |
74 | exit(1); | |
75 | } | |
76 | ||
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; | |
80 | IOReturn ioret; | |
81 | ||
82 | amfi = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleMobileFileIntegrity")); | |
83 | if (amfi == IO_OBJECT_NULL) { | |
84 | fprintf(stderr, "client: unable to find AppleMobileFileIntegrity service\n"); | |
85 | exit(1); | |
86 | } | |
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); | |
90 | exit(1); | |
91 | } | |
92 | ||
93 | printf("client: Found the matching io_connect port = %d\n", connect); | |
94 | ||
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; | |
103 | ||
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; | |
109 | ||
110 | mach_msg_option_t option = MACH_SEND_MSG; | |
111 | ||
112 | printf("client: Sending request (expecting it to fail) \n"); | |
113 | mach_msg_return_t mret = mach_msg(request, | |
114 | option, | |
115 | (mach_msg_size_t)client_args.request_msg_size, | |
116 | 0, | |
117 | MACH_PORT_NULL, | |
118 | MACH_MSG_TIMEOUT_NONE, | |
119 | MACH_PORT_NULL); | |
120 | ||
121 | printf("client: mach_msg returned %x\n", mret); | |
122 | if (mret != MACH_SEND_INVALID_RIGHT) { | |
123 | mach_error("client: mach_msg", mret); | |
124 | exit(1); | |
125 | } | |
126 | ||
127 | printf("It should never reach here\n"); | |
128 | ||
129 | return 0; | |
130 | } |