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, &current_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