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