]>
Commit | Line | Data |
---|---|---|
f427ee49 A |
1 | #include <servers/bootstrap.h> |
2 | #include <mach/mach.h> | |
3 | #include <mach/message.h> | |
4 | #include <stdlib.h> | |
5 | #include <sys/sysctl.h> | |
6 | #include <unistd.h> | |
7 | #include <pthread.h> | |
8 | ||
9 | #ifdef T_NAMESPACE | |
10 | #undef T_NAMESPACE | |
11 | #endif | |
12 | ||
13 | #include <darwintest.h> | |
14 | #include <darwintest_utils.h> | |
15 | #include <darwintest_multiprocess.h> | |
16 | ||
17 | #define MACH_RCV_OPTIONS (MACH_RCV_MSG | MACH_RCV_LARGE | MACH_RCV_LARGE_IDENTITY | \ | |
18 | MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AV) | \ | |
19 | MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)) | |
20 | ||
21 | T_GLOBAL_META(T_META_RUN_CONCURRENTLY(true), T_META_NAMESPACE("xnu.ipc")); | |
22 | ||
23 | typedef struct { | |
24 | mach_msg_header_t header; | |
25 | mach_msg_mac_trailer_t trailer; // subtract this when sending | |
26 | } ipc_simple_message; | |
27 | ||
28 | static ipc_simple_message icm_request = {}; | |
29 | ||
30 | struct args { | |
31 | const char *progname; | |
32 | int verbose; | |
33 | int num_msgs; | |
34 | char *server_port_name; | |
35 | mach_port_t server_port; | |
36 | int request_msg_size; | |
37 | void *request_msg; | |
38 | }; | |
39 | ||
40 | void parse_args(struct args *args); | |
41 | void* create_buffer(int *buffer_size); | |
42 | void client(struct args *args); | |
43 | void server_setup(struct args* args); | |
44 | void *server(void *thread_args); | |
45 | ||
46 | void | |
47 | parse_args(struct args *args) | |
48 | { | |
49 | args->verbose = 0; | |
50 | args->server_port_name = "TEST_FILTER_POLICY"; | |
51 | args->server_port = MACH_PORT_NULL; | |
52 | args->num_msgs = 1; | |
53 | args->request_msg_size = sizeof(ipc_simple_message); | |
54 | args->request_msg = &icm_request; | |
55 | } | |
56 | ||
57 | /* Create a mach IPC listener which will respond to the client's message */ | |
58 | void | |
59 | server_setup(struct args* args) | |
60 | { | |
61 | kern_return_t ret; | |
62 | mach_port_t bsport; | |
63 | ||
64 | ret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, | |
65 | &args->server_port); | |
66 | T_ASSERT_MACH_SUCCESS(ret, "server: mach_port_allocate()"); | |
67 | ||
68 | ret = mach_port_insert_right(mach_task_self(), args->server_port, args->server_port, | |
69 | MACH_MSG_TYPE_MAKE_SEND); | |
70 | T_ASSERT_MACH_SUCCESS(ret, "server: mach_port_insert_right()"); | |
71 | ||
72 | ret = task_get_bootstrap_port(mach_task_self(), &bsport); | |
73 | T_ASSERT_MACH_SUCCESS(ret, "server: task_get_bootstrap_port()"); | |
74 | ||
75 | ret = bootstrap_register(bsport, args->server_port_name, args->server_port); | |
76 | T_ASSERT_MACH_SUCCESS(ret, "server: bootstrap_register()"); | |
77 | ||
78 | T_LOG("server: waiting for IPC messages from client on port '%s'.\n", | |
79 | args->server_port_name); | |
80 | } | |
81 | ||
82 | /* Server process loop | |
83 | * | |
84 | * Listens for message. | |
85 | * | |
86 | */ | |
87 | void * | |
88 | server(void *thread_args) | |
89 | { | |
90 | mach_msg_header_t *request; | |
91 | mach_msg_option_t rcvoption = MACH_RCV_OPTIONS; | |
92 | kern_return_t ret; | |
93 | mach_msg_trailer_t *tlr = NULL; | |
94 | mach_msg_mac_trailer_t *mac_tlr; | |
95 | mach_msg_filter_id filter_policy_id = 0; | |
96 | pid_t pid = getpid(); | |
97 | struct args *args = (struct args*)thread_args; | |
98 | ||
99 | request = (mach_msg_header_t *)args->request_msg; | |
100 | ||
101 | T_LOG("server(%d): Awaiting message", pid); | |
102 | ret = mach_msg(request, | |
103 | rcvoption, | |
104 | 0, | |
105 | sizeof(ipc_simple_message), | |
106 | args->server_port, | |
107 | MACH_MSG_TIMEOUT_NONE, | |
108 | MACH_PORT_NULL); | |
109 | ||
110 | T_ASSERT_MACH_SUCCESS(ret, "server: mach_msg receive"); | |
111 | T_ASSERT_EQ(request->msgh_id, 500, "server: msg id = %d", request->msgh_id); | |
112 | ||
113 | tlr = (mach_msg_trailer_t *)((unsigned char *)request + | |
114 | round_msg(request->msgh_size)); | |
115 | // The trailer should always be of format zero. | |
116 | if (tlr->msgh_trailer_type == MACH_MSG_TRAILER_FORMAT_0) { | |
117 | if (tlr->msgh_trailer_size >= sizeof(mach_msg_mac_trailer_t)) { | |
118 | mac_tlr = (mach_msg_mac_trailer_t *)tlr; | |
119 | filter_policy_id = mac_tlr->msgh_ad; | |
120 | } | |
121 | } | |
122 | ||
123 | T_LOG("server: received the filter policy id = %d", filter_policy_id); | |
124 | T_ASSERT_EQ(filter_policy_id, MACH_MSG_FILTER_POLICY_ALLOW, "server: filter policy allow sentinel"); | |
125 | mach_msg_destroy(request); | |
126 | ||
127 | return NULL; | |
128 | } | |
129 | ||
130 | T_HELPER_DECL(client_not_filtered, "Send a message to the server which shouldn't be filtered") | |
131 | { | |
132 | T_LOG("client(%d): Prepare to send a message", getpid()); | |
133 | struct args args = {}; | |
134 | mach_port_t bsport; | |
135 | ||
136 | parse_args(&args); | |
137 | args.request_msg_size -= sizeof(mach_msg_mac_trailer_t); | |
138 | ||
139 | //Find the bootstrap port | |
140 | kern_return_t ret = task_get_bootstrap_port(mach_task_self(), &bsport); | |
141 | T_ASSERT_MACH_SUCCESS(ret, "client: task_get_bootstrap_port()"); | |
142 | ||
143 | //Look up the service port | |
144 | ret = bootstrap_look_up(bsport, (char *)args.server_port_name, | |
145 | &args.server_port); | |
146 | T_ASSERT_MACH_SUCCESS(ret, "client: bootstrap_look_up()"); | |
147 | ||
148 | //Construct the message | |
149 | mach_msg_header_t *request = (mach_msg_header_t *)args.request_msg; | |
150 | request->msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_COPY_SEND, 0, 0, 0); | |
151 | request->msgh_size = (mach_msg_size_t)args.request_msg_size; | |
152 | request->msgh_remote_port = args.server_port; | |
153 | request->msgh_local_port = MACH_PORT_NULL; | |
154 | request->msgh_id = 500; | |
155 | ||
156 | T_LOG("client: Sending request"); | |
157 | ret = mach_msg_send(request); | |
158 | T_ASSERT_MACH_SUCCESS(ret, "client: mach_msg_send()"); | |
159 | } | |
160 | ||
161 | T_DECL(filter_policy_id, "Send a message and check the filter policy id received in the trailer") | |
162 | { | |
163 | struct args args = {}; | |
164 | dt_helper_t helpers[1]; | |
165 | pthread_t server_thread; | |
166 | ||
167 | T_SETUPBEGIN; | |
168 | parse_args(&args); | |
169 | server_setup(&args); | |
170 | T_SETUPEND; | |
171 | ||
172 | helpers[0] = dt_fork_helper("client_not_filtered"); | |
173 | int ret = pthread_create(&server_thread, NULL, server, &args); | |
174 | T_ASSERT_POSIX_SUCCESS(ret, "pthread_create server_thread"); | |
175 | pthread_detach(server_thread); | |
176 | ||
177 | dt_run_helpers(helpers, 1, 30); | |
178 | } |