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 <stdio.h>
6 #include <stdlib.h>
7 
8 #include <zircon/process.h>
9 #include <zircon/syscalls.h>
10 #include <zircon/syscalls/object.h>
11 #include <unittest/unittest.h>
12 
handle_replace_test(void)13 static bool handle_replace_test(void) {
14     BEGIN_TEST;
15 
16     zx_handle_t event = ZX_HANDLE_INVALID;
17     ASSERT_EQ(ZX_OK, zx_event_create(0u, &event), "");
18 
19     zx_handle_t replaced = ZX_HANDLE_INVALID;
20     ASSERT_EQ(ZX_OK, zx_handle_replace(event, ZX_RIGHTS_BASIC, &replaced), "");
21     ASSERT_EQ(ZX_ERR_BAD_HANDLE, zx_handle_close(event), "");
22 
23     zx_handle_t failed = ZX_HANDLE_INVALID;
24     ASSERT_EQ(ZX_ERR_INVALID_ARGS, zx_handle_replace(replaced, ZX_RIGHT_SIGNAL, &failed), "");
25     ASSERT_EQ(ZX_ERR_BAD_HANDLE, zx_handle_close(replaced), "");
26     ASSERT_EQ(ZX_HANDLE_INVALID, failed, "");
27 
28     END_TEST;
29 }
30 
handle_info_test(void)31 static bool handle_info_test(void) {
32     BEGIN_TEST;
33 
34     zx_handle_t event;
35     ASSERT_EQ(zx_event_create(0u, &event), 0, "");
36     zx_handle_t duped;
37     zx_status_t status = zx_handle_duplicate(event, ZX_RIGHT_SAME_RIGHTS, &duped);
38     ASSERT_EQ(status, ZX_OK, "");
39 
40     ASSERT_EQ(zx_object_get_info(event, ZX_INFO_HANDLE_VALID, NULL, 0u, NULL, NULL), ZX_OK,
41               "handle should be valid");
42     ASSERT_EQ(zx_handle_close(event), ZX_OK, "failed to close the handle");
43     ASSERT_EQ(zx_object_get_info(event, ZX_INFO_HANDLE_VALID, NULL, 0u, NULL, NULL), ZX_ERR_BAD_HANDLE,
44               "handle should be valid");
45 
46     zx_info_handle_basic_t info = {};
47     ASSERT_EQ(zx_object_get_info(duped, ZX_INFO_HANDLE_BASIC, &info, 4u, NULL, NULL),
48               ZX_ERR_BUFFER_TOO_SMALL, "bad struct size validation");
49 
50     status = zx_object_get_info(duped, ZX_INFO_HANDLE_BASIC, &info, sizeof(info), NULL, NULL);
51     ASSERT_EQ(status, ZX_OK, "handle should be valid");
52 
53     const zx_rights_t evr = ZX_RIGHTS_BASIC | ZX_RIGHT_SIGNAL;
54 
55     EXPECT_GT(info.koid, 0ULL, "object id should be positive");
56     EXPECT_EQ(info.type, (uint32_t)ZX_OBJ_TYPE_EVENT, "handle should be an event");
57     EXPECT_EQ(info.rights, evr, "wrong set of rights");
58     EXPECT_EQ(info.props, (uint32_t)ZX_OBJ_PROP_WAITABLE, "");
59     EXPECT_EQ(info.related_koid, 0ULL, "events don't have associated koid");
60 
61     zx_handle_close(event);
62     zx_handle_close(duped);
63 
64     END_TEST;
65 }
66 
handle_related_koid_test(void)67 static bool handle_related_koid_test(void) {
68     BEGIN_TEST;
69 
70     zx_info_handle_basic_t info0 = {};
71     zx_info_handle_basic_t info1 = {};
72 
73     zx_status_t status = zx_object_get_info(
74         zx_job_default(), ZX_INFO_HANDLE_BASIC, &info0, sizeof(info0), NULL, NULL);
75     ASSERT_EQ(status, ZX_OK, "");
76 
77     status = zx_object_get_info(
78         zx_process_self(), ZX_INFO_HANDLE_BASIC, &info1, sizeof(info1), NULL, NULL);
79     ASSERT_EQ(status, ZX_OK, "");
80 
81     EXPECT_EQ(info0.type, (uint32_t)ZX_OBJ_TYPE_JOB, "");
82     EXPECT_EQ(info1.type, (uint32_t)ZX_OBJ_TYPE_PROCESS, "");
83 
84     zx_handle_t thread;
85     status = zx_thread_create(zx_process_self(), "hitr", 4, 0u, &thread);
86     ASSERT_EQ(status, ZX_OK, "");
87 
88     zx_info_handle_basic_t info2 = {};
89 
90     status = zx_object_get_info(
91         thread, ZX_INFO_HANDLE_BASIC, &info2, sizeof(info2), NULL, NULL);
92     ASSERT_EQ(status, ZX_OK, "");
93 
94     EXPECT_EQ(info2.type, (uint32_t)ZX_OBJ_TYPE_THREAD, "");
95 
96     // The related koid of a process is its job and this test assumes that the
97     // default job is in fact the parent job of this test. Equivalently, a thread's
98     // associated koid is the process koid.
99     EXPECT_EQ(info1.related_koid, info0.koid, "");
100     EXPECT_EQ(info2.related_koid, info1.koid, "");
101 
102     zx_handle_close(thread);
103 
104     zx_handle_t sock0, sock1;
105     status = zx_socket_create(0u, &sock0, &sock1);
106     ASSERT_EQ(status, ZX_OK, "");
107 
108     status = zx_object_get_info(
109         sock0, ZX_INFO_HANDLE_BASIC, &info0, sizeof(info0), NULL, NULL);
110     ASSERT_EQ(status, ZX_OK, "");
111 
112     status = zx_object_get_info(
113         sock1, ZX_INFO_HANDLE_BASIC, &info1, sizeof(info1), NULL, NULL);
114     ASSERT_EQ(status, ZX_OK, "");
115 
116     EXPECT_EQ(info0.type, (uint32_t)ZX_OBJ_TYPE_SOCKET, "");
117     EXPECT_EQ(info1.type, (uint32_t)ZX_OBJ_TYPE_SOCKET, "");
118 
119     // The related koid of a socket pair are each other koids.
120     EXPECT_EQ(info0.related_koid, info1.koid, "");
121     EXPECT_EQ(info1.related_koid, info0.koid, "");
122 
123     zx_handle_close(sock0);
124     zx_handle_close(sock1);
125     END_TEST;
126 }
127 
handle_rights_test(void)128 static bool handle_rights_test(void) {
129     BEGIN_TEST;
130 
131     zx_handle_t event;
132     ASSERT_EQ(zx_event_create(0u, &event), 0, "");
133     zx_handle_t duped_ro, duped_ro2;
134     ASSERT_EQ(zx_handle_duplicate(event, ZX_RIGHT_WAIT, &duped_ro), ZX_OK, "");
135     ASSERT_EQ(zx_handle_duplicate(event, ZX_RIGHT_WAIT, &duped_ro2), ZX_OK, "");
136 
137     zx_info_handle_basic_t info = {};
138     zx_status_t status = zx_object_get_info(duped_ro, ZX_INFO_HANDLE_BASIC, &info, sizeof(info), NULL, NULL);
139     ASSERT_EQ(status, ZX_OK, "handle should be valid");
140 
141     ASSERT_EQ(info.rights, ZX_RIGHT_WAIT, "wrong set of rights");
142 
143     zx_handle_t h;
144     status = zx_handle_duplicate(duped_ro, ZX_RIGHT_SAME_RIGHTS, &h);
145     ASSERT_EQ(status, ZX_ERR_ACCESS_DENIED, "should fail rights check");
146 
147     status = zx_handle_duplicate(event, ZX_RIGHT_EXECUTE | ZX_RIGHT_WAIT, &h);
148     ASSERT_EQ(status, ZX_ERR_INVALID_ARGS, "cannot upgrade rights");
149 
150     ASSERT_EQ(zx_handle_replace(duped_ro, ZX_RIGHT_SIGNAL | ZX_RIGHT_WAIT, &h), ZX_ERR_INVALID_ARGS,
151               "cannot upgrade rights");
152     // duped_ro1 should now be invalid.
153     ASSERT_EQ(zx_handle_close(duped_ro), ZX_ERR_BAD_HANDLE, "replaced handle should be invalid on failure");
154 
155     status = zx_handle_replace(duped_ro2, ZX_RIGHT_SAME_RIGHTS, &h);
156     ASSERT_EQ(status, ZX_OK, "should be able to replace handle");
157     // duped_ro2 should now be invalid.
158 
159     ASSERT_EQ(zx_handle_close(event), ZX_OK, "failed to close original handle");
160     ASSERT_EQ(zx_handle_close(duped_ro2), ZX_ERR_BAD_HANDLE, "replaced handle should be invalid on success");
161     ASSERT_EQ(zx_handle_close(h), ZX_OK, "failed to close replacement handle");
162 
163     END_TEST;
164 }
165 
166 BEGIN_TEST_CASE(handle_info_tests)
RUN_TEST(handle_replace_test)167 RUN_TEST(handle_replace_test)
168 RUN_TEST(handle_info_test)
169 RUN_TEST(handle_related_koid_test)
170 RUN_TEST(handle_rights_test)
171 END_TEST_CASE(handle_info_tests)
172 
173 #ifndef BUILD_COMBINED_TESTS
174 int main(int argc, char** argv) {
175     return unittest_run_all_tests(argc, argv) ? 0 : -1;
176 }
177 #endif
178