1 // Copyright 2016 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <inttypes.h>
6 #include <stdbool.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <threads.h>
11
12 #include <lib/fdio/util.h>
13 #include <test-utils/test-utils.h>
14 #include <unittest/unittest.h>
15 #include <zircon/compiler.h>
16 #include <zircon/process.h>
17 #include <zircon/processargs.h>
18 #include <zircon/syscalls.h>
19 #include <zircon/syscalls/object.h>
20 #include <zircon/threads.h>
21
get_rights(zx_handle_t handle,zx_rights_t * rights)22 static bool get_rights(zx_handle_t handle, zx_rights_t* rights) {
23 zx_info_handle_basic_t info;
24 ASSERT_EQ(zx_object_get_info(handle, ZX_INFO_HANDLE_BASIC, &info, sizeof(info), NULL, NULL), ZX_OK, "");
25 *rights = info.rights;
26 return true;
27 }
28
get_new_rights(zx_handle_t handle,zx_rights_t new_rights,zx_handle_t * new_handle)29 static bool get_new_rights(zx_handle_t handle, zx_rights_t new_rights, zx_handle_t* new_handle) {
30 ASSERT_EQ(zx_handle_duplicate(handle, new_rights, new_handle), ZX_OK, "");
31 return true;
32 }
33
34 // |object| must have ZX_RIGHT_{GET,SET}_PROPERTY.
35
test_name_property(zx_handle_t object)36 static bool test_name_property(zx_handle_t object) {
37 char set_name[ZX_MAX_NAME_LEN];
38 char get_name[ZX_MAX_NAME_LEN];
39
40 // name with extra garbage at the end
41 memset(set_name, 'A', sizeof(set_name));
42 set_name[1] = '\0';
43
44 EXPECT_EQ(zx_object_set_property(object, ZX_PROP_NAME,
45 set_name, sizeof(set_name)),
46 ZX_OK, "");
47 EXPECT_EQ(zx_object_get_property(object, ZX_PROP_NAME,
48 get_name, sizeof(get_name)),
49 ZX_OK, "");
50 EXPECT_EQ(get_name[0], 'A', "");
51 for (size_t i = 1; i < sizeof(get_name); i++) {
52 EXPECT_EQ(get_name[i], '\0', "");
53 }
54
55 // empty name
56 strcpy(set_name, "");
57 EXPECT_EQ(zx_object_set_property(object, ZX_PROP_NAME,
58 set_name, strlen(set_name)),
59 ZX_OK, "");
60 EXPECT_EQ(zx_object_get_property(object, ZX_PROP_NAME,
61 get_name, sizeof(get_name)),
62 ZX_OK, "");
63 EXPECT_EQ(strcmp(get_name, set_name), 0, "");
64
65 // largest possible name
66 memset(set_name, 'x', sizeof(set_name) - 1);
67 set_name[sizeof(set_name) - 1] = '\0';
68 EXPECT_EQ(zx_object_set_property(object, ZX_PROP_NAME,
69 set_name, strlen(set_name)),
70 ZX_OK, "");
71 EXPECT_EQ(zx_object_get_property(object, ZX_PROP_NAME,
72 get_name, sizeof(get_name)),
73 ZX_OK, "");
74 EXPECT_EQ(strcmp(get_name, set_name), 0, "");
75
76 // too large a name by 1
77 memset(set_name, 'x', sizeof(set_name));
78 EXPECT_EQ(zx_object_set_property(object, ZX_PROP_NAME,
79 set_name, sizeof(set_name)),
80 ZX_OK, "");
81
82 zx_rights_t current_rights;
83 if (get_rights(object, ¤t_rights)) {
84 zx_rights_t cant_set_rights = current_rights &= ~ZX_RIGHT_SET_PROPERTY;
85 zx_handle_t cant_set;
86 if (get_new_rights(object, cant_set_rights, &cant_set)) {
87 EXPECT_EQ(zx_object_set_property(cant_set, ZX_PROP_NAME, "", 0), ZX_ERR_ACCESS_DENIED, "");
88 zx_handle_close(cant_set);
89 }
90 }
91
92 return true;
93 }
94
job_name_test(void)95 static bool job_name_test(void) {
96 BEGIN_TEST;
97
98 zx_handle_t testjob;
99 zx_status_t s = zx_job_create(zx_job_default(), 0, &testjob);
100 EXPECT_EQ(s, ZX_OK, "");
101
102 bool success = test_name_property(testjob);
103 if (!success)
104 return false;
105
106 zx_handle_close(testjob);
107 END_TEST;
108 }
109
process_name_test(void)110 static bool process_name_test(void) {
111 BEGIN_TEST;
112
113 zx_handle_t self = zx_process_self();
114 bool success = test_name_property(self);
115 if (!success)
116 return false;
117
118 END_TEST;
119 }
120
thread_name_test(void)121 static bool thread_name_test(void) {
122 BEGIN_TEST;
123
124 zx_handle_t main_thread = thrd_get_zx_handle(thrd_current());
125 unittest_printf("thread handle %d\n", main_thread);
126 bool success = test_name_property(main_thread);
127 if (!success)
128 return false;
129
130 END_TEST;
131 }
132
vmo_name_test(void)133 static bool vmo_name_test(void) {
134 BEGIN_TEST;
135
136 zx_handle_t vmo;
137 ASSERT_EQ(zx_vmo_create(16, 0u, &vmo), ZX_OK, "");
138 unittest_printf("VMO handle %d\n", vmo);
139
140 char name[ZX_MAX_NAME_LEN];
141 memset(name, 'A', sizeof(name));
142
143 // Name should start out empty.
144 EXPECT_EQ(zx_object_get_property(vmo, ZX_PROP_NAME, name, sizeof(name)),
145 ZX_OK, "");
146 for (size_t i = 0; i < sizeof(name); i++) {
147 EXPECT_EQ(name[i], '\0', "");
148 }
149
150 // Check the rest.
151 bool success = test_name_property(vmo);
152 if (!success)
153 return false;
154
155 END_TEST;
156 }
157
158 // Returns a job, its child job, and its grandchild job.
159 #define NUM_TEST_JOBS 3
get_test_jobs(zx_handle_t jobs_out[NUM_TEST_JOBS])160 static zx_status_t get_test_jobs(zx_handle_t jobs_out[NUM_TEST_JOBS]) {
161 static zx_handle_t test_jobs[NUM_TEST_JOBS] = {ZX_HANDLE_INVALID};
162
163 if (test_jobs[0] == ZX_HANDLE_INVALID) {
164 zx_handle_t root;
165 zx_status_t s = zx_job_create(zx_job_default(), 0, &root);
166 if (s != ZX_OK) {
167 EXPECT_EQ(s, ZX_OK, "root job"); // Poison the test
168 return s;
169 }
170 zx_handle_t child;
171 s = zx_job_create(root, 0, &child);
172 if (s != ZX_OK) {
173 EXPECT_EQ(s, ZX_OK, "child job");
174 zx_task_kill(root);
175 zx_handle_close(root);
176 return s;
177 }
178 zx_handle_t gchild;
179 s = zx_job_create(child, 0, &gchild);
180 if (s != ZX_OK) {
181 EXPECT_EQ(s, ZX_OK, "grandchild job");
182 zx_task_kill(root); // Kills child, too
183 zx_handle_close(child);
184 zx_handle_close(root);
185 return s;
186 }
187 test_jobs[0] = root;
188 test_jobs[1] = child;
189 test_jobs[2] = gchild;
190 }
191 memcpy(jobs_out, test_jobs, sizeof(test_jobs));
192 return ZX_OK;
193 }
194
socket_buffer_test(void)195 static bool socket_buffer_test(void) {
196 BEGIN_TEST;
197
198 zx_handle_t sockets[2];
199 ASSERT_EQ(zx_socket_create(0, &sockets[0], &sockets[1]), ZX_OK, "");
200
201 // Check the buffer size after a write.
202 uint8_t buf[8] = {};
203 size_t actual;
204 ASSERT_EQ(zx_socket_write(sockets[1], 0, buf, sizeof(buf), &actual), ZX_OK, "");
205 EXPECT_EQ(actual, sizeof(buf), "");
206
207 zx_info_socket_t info;
208
209 memset(&info, 0, sizeof(info));
210 ASSERT_EQ(zx_object_get_info(sockets[0], ZX_INFO_SOCKET, &info, sizeof(info), NULL, NULL), ZX_OK, "");
211 EXPECT_EQ(info.options, 0u, "");
212 EXPECT_GT(info.rx_buf_max, 0u, "");
213 EXPECT_EQ(info.rx_buf_size, sizeof(buf), "");
214 EXPECT_EQ(info.rx_buf_available, sizeof(buf), "");
215 EXPECT_GT(info.tx_buf_max, 0u, "");
216 EXPECT_EQ(info.tx_buf_size, 0u, "");
217
218 memset(&info, 0, sizeof(info));
219 ASSERT_EQ(zx_object_get_info(sockets[1], ZX_INFO_SOCKET, &info, sizeof(info), NULL, NULL), ZX_OK, "");
220 EXPECT_EQ(info.options, 0u, "");
221 EXPECT_GT(info.rx_buf_max, 0u, "");
222 EXPECT_EQ(info.rx_buf_size, 0u, "");
223 EXPECT_EQ(info.rx_buf_available, 0u, "");
224 EXPECT_GT(info.tx_buf_max, 0u, "");
225 EXPECT_EQ(info.tx_buf_size, sizeof(buf), "");
226
227
228 // Check TX buf goes to zero on peer closed.
229 zx_handle_close(sockets[0]);
230
231 memset(&info, 0, sizeof(info));
232 ASSERT_EQ(zx_object_get_info(sockets[1], ZX_INFO_SOCKET, &info, sizeof(info), NULL, NULL), ZX_OK, "");
233 EXPECT_EQ(info.options, 0u, "");
234 EXPECT_GT(info.rx_buf_max, 0u, "");
235 EXPECT_EQ(info.rx_buf_size, 0u, "");
236 EXPECT_EQ(info.rx_buf_available, 0u, "");
237 EXPECT_EQ(info.tx_buf_max, 0u, "");
238 EXPECT_EQ(info.tx_buf_size, 0u, "");
239
240 zx_handle_close(sockets[1]);
241
242 ASSERT_EQ(zx_socket_create(ZX_SOCKET_DATAGRAM, &sockets[0], &sockets[1]), ZX_OK, "");
243
244 memset(&info, 0, sizeof(info));
245 ASSERT_EQ(zx_object_get_info(sockets[0], ZX_INFO_SOCKET, &info, sizeof(info), NULL, NULL), ZX_OK, "");
246 EXPECT_EQ(info.options, ZX_SOCKET_DATAGRAM, "");
247 EXPECT_GT(info.rx_buf_max, 0u, "");
248 EXPECT_EQ(info.rx_buf_size, 0u, "");
249 EXPECT_EQ(info.rx_buf_available, 0u, "");
250 EXPECT_GT(info.tx_buf_max, 0u, "");
251 EXPECT_EQ(info.tx_buf_size, 0u, "");
252
253 ASSERT_EQ(zx_socket_write(sockets[1], 0, buf, sizeof(buf), &actual), ZX_OK, "");
254 EXPECT_EQ(actual, sizeof(buf), "");
255
256 memset(&info, 0, sizeof(info));
257 ASSERT_EQ(zx_object_get_info(sockets[0], ZX_INFO_SOCKET, &info, sizeof(info), NULL, NULL), ZX_OK, "");
258 EXPECT_EQ(info.options, ZX_SOCKET_DATAGRAM, "");
259 EXPECT_GT(info.rx_buf_max, 0u, "");
260 EXPECT_EQ(info.rx_buf_size, 8u, "");
261 EXPECT_EQ(info.rx_buf_available, 8u, "");
262 EXPECT_GT(info.tx_buf_max, 0u, "");
263 EXPECT_EQ(info.tx_buf_size, 0u, "");
264
265 ASSERT_EQ(zx_socket_write(sockets[1], 0, buf, sizeof(buf) / 2, &actual), ZX_OK, "");
266 EXPECT_EQ(actual, sizeof(buf) / 2, "");
267
268 memset(&info, 0, sizeof(info));
269 ASSERT_EQ(zx_object_get_info(sockets[0], ZX_INFO_SOCKET, &info, sizeof(info), NULL, NULL), ZX_OK, "");
270 EXPECT_EQ(info.options, ZX_SOCKET_DATAGRAM, "");
271 EXPECT_GT(info.rx_buf_max, 0u, "");
272 EXPECT_EQ(info.rx_buf_size, 12u, "");
273 EXPECT_EQ(info.rx_buf_available, 8u, "");
274 EXPECT_GT(info.tx_buf_max, 0u, "");
275 EXPECT_EQ(info.tx_buf_size, 0u, "");
276
277 zx_handle_close_many(sockets, 2);
278
279 END_TEST;
280 }
281
282 #if defined(__x86_64__)
283
read_gs(void)284 static uintptr_t read_gs(void) {
285 uintptr_t gs;
286 __asm__ __volatile__("mov %%gs:0,%0"
287 : "=r"(gs));
288 return gs;
289 }
290
do_nothing(void * unused)291 static int do_nothing(void* unused) {
292 for (;;) {
293 }
294 return 0;
295 }
296
fs_invalid_test(void)297 static bool fs_invalid_test(void) {
298 BEGIN_TEST;
299
300 // The success case of fs is hard to explicitly test, but is
301 // exercised all the time (ie userspace would explode instantly if
302 // it was broken). Since we will be soon adding a corresponding
303 // mechanism for gs, don't worry about testing success.
304
305 uintptr_t fs_storage;
306 uintptr_t fs_location = (uintptr_t)&fs_storage;
307
308 // All the failures:
309
310 // Try a thread other than the current one.
311 thrd_t t;
312 int success = thrd_create(&t, &do_nothing, NULL);
313 ASSERT_EQ(success, thrd_success, "");
314 zx_handle_t other_thread = thrd_get_zx_handle(t);
315 zx_status_t status = zx_object_set_property(other_thread, ZX_PROP_REGISTER_FS,
316 &fs_location, sizeof(fs_location));
317 ASSERT_EQ(status, ZX_ERR_ACCESS_DENIED, "");
318
319 // Try a non-thread object type.
320 status = zx_object_set_property(zx_process_self(), ZX_PROP_REGISTER_FS,
321 &fs_location, sizeof(fs_location));
322 ASSERT_EQ(status, ZX_ERR_WRONG_TYPE, "");
323
324 // Not enough buffer to hold the property value.
325 status = zx_object_set_property(zx_thread_self(), ZX_PROP_REGISTER_FS,
326 &fs_location, sizeof(fs_location) - 1);
327 ASSERT_EQ(status, ZX_ERR_BUFFER_TOO_SMALL, "");
328
329 // A non-canonical vaddr.
330 uintptr_t noncanonical_fs_location = fs_location | (1ull << 47);
331 status = zx_object_set_property(zx_thread_self(), ZX_PROP_REGISTER_FS,
332 &noncanonical_fs_location,
333 sizeof(noncanonical_fs_location));
334 ASSERT_EQ(status, ZX_ERR_INVALID_ARGS, "");
335
336 // A non-userspace vaddr.
337 uintptr_t nonuserspace_fs_location = 0xffffffff40000000;
338 status = zx_object_set_property(zx_thread_self(), ZX_PROP_REGISTER_FS,
339 &nonuserspace_fs_location,
340 sizeof(nonuserspace_fs_location));
341 ASSERT_EQ(status, ZX_ERR_INVALID_ARGS, "");
342
343 END_TEST;
344 }
345
gs_test(void)346 static bool gs_test(void) {
347 BEGIN_TEST;
348
349 // First test the success case.
350 const uintptr_t expected = 0xfeedfacefeedface;
351
352 uintptr_t gs_storage = expected;
353 uintptr_t gs_location = (uintptr_t)&gs_storage;
354
355 zx_status_t status = zx_object_set_property(zx_thread_self(), ZX_PROP_REGISTER_GS,
356 &gs_location, sizeof(gs_location));
357 ASSERT_EQ(status, ZX_OK, "");
358 ASSERT_EQ(read_gs(), expected, "");
359
360 // All the failures:
361
362 // Try a thread other than the current one.
363 thrd_t t;
364 int success = thrd_create(&t, &do_nothing, NULL);
365 ASSERT_EQ(success, thrd_success, "");
366 zx_handle_t other_thread = thrd_get_zx_handle(t);
367 status = zx_object_set_property(other_thread, ZX_PROP_REGISTER_GS,
368 &gs_location, sizeof(gs_location));
369 ASSERT_EQ(status, ZX_ERR_ACCESS_DENIED, "");
370
371 // Try a non-thread object type.
372 status = zx_object_set_property(zx_process_self(), ZX_PROP_REGISTER_GS,
373 &gs_location, sizeof(gs_location));
374 ASSERT_EQ(status, ZX_ERR_WRONG_TYPE, "");
375
376 // Not enough buffer to hold the property value.
377 status = zx_object_set_property(zx_thread_self(), ZX_PROP_REGISTER_GS,
378 &gs_location, sizeof(gs_location) - 1);
379 ASSERT_EQ(status, ZX_ERR_BUFFER_TOO_SMALL, "");
380
381 // A non-canonical vaddr.
382 uintptr_t noncanonical_gs_location = gs_location | (1ull << 47);
383 status = zx_object_set_property(zx_thread_self(), ZX_PROP_REGISTER_GS,
384 &noncanonical_gs_location,
385 sizeof(noncanonical_gs_location));
386 ASSERT_EQ(status, ZX_ERR_INVALID_ARGS, "");
387
388 // A non-userspace vaddr.
389 uintptr_t nonuserspace_gs_location = 0xffffffff40000000;
390 status = zx_object_set_property(zx_thread_self(), ZX_PROP_REGISTER_GS,
391 &nonuserspace_gs_location,
392 sizeof(nonuserspace_gs_location));
393 ASSERT_EQ(status, ZX_ERR_INVALID_ARGS, "");
394
395 END_TEST;
396 }
397
398 #endif // defined(__x86_64__)
399
400 BEGIN_TEST_CASE(property_tests)
401 RUN_TEST(process_name_test);
402 RUN_TEST(thread_name_test);
403 RUN_TEST(job_name_test);
404 RUN_TEST(vmo_name_test);
405 RUN_TEST(socket_buffer_test);
406 #if defined(__x86_64__)
407 RUN_TEST(fs_invalid_test)
RUN_TEST(gs_test)408 RUN_TEST(gs_test)
409 #endif
410 END_TEST_CASE(property_tests)
411
412 int main(int argc, char** argv) {
413 bool success = unittest_run_all_tests(argc, argv);
414 return success ? 0 : -1;
415 }
416