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 <assert.h>
6#include <stdbool.h>
7#include <stdio.h>
8#include <stdlib.h>
9
10#include <zircon/process.h>
11#include <zircon/rights.h>
12#include <zircon/syscalls.h>
13#include <zircon/syscalls/policy.h>
14
15#include <mini-process/mini-process.h>
16#include <unittest/unittest.h>
17
18static const char process_name[] = "job-test-p";
19
20extern zx_handle_t root_job;
21
22static bool basic_test(void) {
23    BEGIN_TEST;
24
25    // Never close the launchpad job.
26    zx_handle_t job_parent = zx_job_default();
27    ASSERT_NE(job_parent, ZX_HANDLE_INVALID, "");
28
29    // If the parent job is valid, one should be able to create a child job
30    // and a child job of the child job.
31    zx_handle_t job_child, job_grandchild;
32    ASSERT_EQ(zx_job_create(job_parent, 0u, &job_child), ZX_OK, "");
33    ASSERT_EQ(zx_job_create(job_child, 0u, &job_grandchild), ZX_OK, "");
34
35    ASSERT_EQ(zx_handle_close(job_child), ZX_OK, "");
36    ASSERT_EQ(zx_handle_close(job_grandchild), ZX_OK, "");
37
38    // If the parent job is not valid it should fail.
39    zx_handle_t job_fail;
40    ASSERT_EQ(zx_job_create(ZX_HANDLE_INVALID, 0u, &job_fail), ZX_ERR_BAD_HANDLE, "");
41
42    END_TEST;
43}
44
45static bool create_test(void) {
46    BEGIN_TEST;
47
48    zx_handle_t job_parent = zx_job_default();
49    ASSERT_NE(job_parent, ZX_HANDLE_INVALID, "");
50
51    zx_handle_t job_child;
52    ASSERT_EQ(zx_job_create(job_parent, 0u, &job_child), ZX_OK, "");
53
54    // Make sure we can create process object with both the parent job and a child job.
55    zx_handle_t process1, vmar1;
56    ASSERT_EQ(zx_process_create(
57        job_parent, process_name, sizeof(process_name), 0u, &process1, &vmar1), ZX_OK, "");
58
59    zx_handle_t process2, vmar2;
60    ASSERT_EQ(zx_process_create(
61        job_child, process_name, sizeof(process_name), 0u, &process2, &vmar2), ZX_OK, "");
62
63    ASSERT_EQ(zx_handle_close(job_child), ZX_OK, "");
64    ASSERT_EQ(zx_handle_close(process1), ZX_OK, "");
65    ASSERT_EQ(zx_handle_close(process2), ZX_OK, "");
66    ASSERT_EQ(zx_handle_close(vmar1), ZX_OK, "");
67    ASSERT_EQ(zx_handle_close(vmar2), ZX_OK, "");
68
69    END_TEST;
70}
71
72static bool create_missing_rights_test(void) {
73    BEGIN_TEST;
74
75    zx_rights_t rights = ZX_DEFAULT_JOB_RIGHTS & ~ZX_RIGHT_WRITE & ~ZX_RIGHT_MANAGE_JOB;
76    zx_handle_t job_parent;
77    zx_status_t status = zx_handle_duplicate(zx_job_default(), rights, &job_parent);
78    ASSERT_EQ(status, ZX_OK, "");
79
80    zx_handle_t job_child;
81    ASSERT_EQ(zx_job_create(job_parent, 0u, &job_child), ZX_ERR_ACCESS_DENIED, "");
82
83    zx_handle_close(job_parent);
84
85    END_TEST;
86}
87
88static bool policy_basic_test(void) {
89    BEGIN_TEST;
90
91    zx_handle_t job_parent = zx_job_default();
92    ASSERT_NE(job_parent, ZX_HANDLE_INVALID, "");
93
94    zx_handle_t job_child;
95    ASSERT_EQ(zx_job_create(job_parent, 0u, &job_child), ZX_OK, "");
96
97    zx_policy_basic_t policy[] = {
98        { ZX_POL_BAD_HANDLE, ZX_POL_ACTION_KILL },
99        { ZX_POL_NEW_CHANNEL, ZX_POL_ACTION_ALLOW | ZX_POL_ACTION_EXCEPTION },
100        { ZX_POL_NEW_FIFO, ZX_POL_ACTION_DENY },
101    };
102
103    ASSERT_EQ(zx_job_set_policy(job_child, ZX_JOB_POL_RELATIVE,
104        ZX_JOB_POL_BASIC, policy, countof(policy)), ZX_OK, "");
105
106    ASSERT_EQ(zx_handle_close(job_child), ZX_OK, "");
107    END_TEST;
108}
109
110static bool kill_test(void) {
111    BEGIN_TEST;
112
113    zx_handle_t job_parent = zx_job_default();
114    ASSERT_NE(job_parent, ZX_HANDLE_INVALID, "");
115
116    zx_handle_t job_child;
117    ASSERT_EQ(zx_job_create(job_parent, 0u, &job_child), ZX_OK, "");
118
119    zx_handle_t event;
120    ASSERT_EQ(zx_event_create(0u, &event), ZX_OK, "");
121
122    zx_handle_t process, thread;
123    ASSERT_EQ(start_mini_process(job_child, event, &process, &thread), ZX_OK, "");
124
125    ASSERT_EQ(zx_task_kill(job_child), ZX_OK, "");
126
127    zx_signals_t signals;
128    ASSERT_EQ(zx_object_wait_one(
129        process, ZX_TASK_TERMINATED, ZX_TIME_INFINITE, &signals), ZX_OK, "");
130    ASSERT_EQ(signals, ZX_TASK_TERMINATED, "");
131
132    ASSERT_EQ(zx_object_wait_one(
133        job_child, ZX_JOB_NO_PROCESSES, ZX_TIME_INFINITE, &signals), ZX_OK, "");
134    ASSERT_EQ(signals, ZX_JOB_NO_PROCESSES | ZX_JOB_NO_JOBS, "");
135
136    // Process should be in the dead state here.
137
138    zx_handle_t job_grandchild;
139    ASSERT_EQ(zx_job_create(job_child, 0u, &job_grandchild), ZX_ERR_BAD_STATE, "");
140
141    ASSERT_EQ(zx_handle_close(thread), ZX_OK, "");
142    ASSERT_EQ(zx_handle_close(process), ZX_OK, "");
143    ASSERT_EQ(start_mini_process(job_child, event, &process, &thread), ZX_ERR_BAD_STATE, "");
144
145    END_TEST;
146}
147
148static bool wait_test(void) {
149    BEGIN_TEST;
150
151    zx_handle_t job_parent = zx_job_default();
152    ASSERT_NE(job_parent, ZX_HANDLE_INVALID, "");
153
154    zx_handle_t job_child;
155    ASSERT_EQ(zx_job_create(job_parent, 0u, &job_child), ZX_OK, "");
156
157    zx_handle_t event;
158    ASSERT_EQ(zx_event_create(0u, &event), ZX_OK, "");
159
160    zx_handle_t process, thread;
161    ASSERT_EQ(start_mini_process(job_child, event, &process, &thread), ZX_OK, "");
162
163    zx_signals_t signals;
164    ASSERT_EQ(zx_object_wait_one(
165        job_child, ZX_JOB_NO_JOBS, ZX_TIME_INFINITE, &signals), ZX_OK, "");
166    ASSERT_EQ(signals, ZX_JOB_NO_JOBS, "");
167
168    zx_nanosleep(zx_deadline_after(ZX_MSEC(5)));
169    ASSERT_EQ(zx_task_kill(process), ZX_OK, "");
170
171    ASSERT_EQ(zx_object_wait_one(
172        job_child, ZX_JOB_NO_PROCESSES, ZX_TIME_INFINITE, &signals), ZX_OK, "");
173    ASSERT_EQ(signals, ZX_JOB_NO_PROCESSES | ZX_JOB_NO_JOBS, "");
174
175    ASSERT_EQ(zx_handle_close(thread), ZX_OK, "");
176    ASSERT_EQ(zx_handle_close(process), ZX_OK, "");
177    ASSERT_EQ(zx_handle_close(job_child), ZX_OK, "");
178
179    END_TEST;
180}
181
182static bool info_task_stats_fails(void) {
183    BEGIN_TEST;
184    zx_info_task_stats_t info;
185    ASSERT_NE(zx_object_get_info(zx_job_default(), ZX_INFO_TASK_STATS,
186                                 &info, sizeof(info), NULL, NULL),
187              ZX_OK,
188              "Just added job support to info_task_status?");
189    // If so, replace this with a real test; see example in process.cpp.
190    END_TEST;
191}
192
193// Show that there is a max job height.
194static bool max_height_smoke(void) {
195    BEGIN_TEST;
196
197    // Get our parent job.
198    zx_handle_t parent_job = zx_job_default();
199
200    // Stack of handles that we need to close.
201    static const int kNumJobs = 128;
202    zx_handle_t *handles = calloc(kNumJobs, sizeof(*handles));
203    ASSERT_NONNULL(handles, "");
204    zx_handle_t *htop = handles;
205
206    // Eat up our max height.
207    while (true) {
208        zx_handle_t child_job;
209        zx_status_t s = zx_job_create(parent_job, 0u, &child_job);
210        if (s != ZX_OK) {
211            break;
212        }
213        // We should hit the max before running out of entries;
214        // this is the core check of this test.
215        ASSERT_LT(htop - handles, kNumJobs,
216                  "Should have seen the max job height");
217        *htop++ = child_job;
218        parent_job = child_job;
219    }
220
221    // We've hit the bottom. Creating a child under this job should fail.
222    zx_handle_t child_job;
223    EXPECT_EQ(zx_job_create(parent_job, 0u, &child_job), ZX_ERR_OUT_OF_RANGE, "");
224
225    // Creating a process should succeed, though.
226    zx_handle_t child_proc;
227    zx_handle_t vmar;
228    ASSERT_EQ(zx_process_create(
229                  parent_job, "test", sizeof("test"), 0u, &child_proc, &vmar),
230              ZX_OK, "");
231    zx_handle_close(vmar);
232    zx_handle_close(child_proc);
233
234    // Clean up.
235    while (htop > handles) {
236        EXPECT_EQ(zx_handle_close(*--htop), ZX_OK, "");
237    }
238    free(handles);
239
240    END_TEST;
241}
242
243BEGIN_TEST_CASE(job_tests)
244RUN_TEST(basic_test)
245RUN_TEST(create_missing_rights_test)
246RUN_TEST(policy_basic_test)
247RUN_TEST(create_test)
248RUN_TEST(kill_test)
249RUN_TEST(wait_test)
250RUN_TEST(info_task_stats_fails)
251RUN_TEST(max_height_smoke)
252END_TEST_CASE(job_tests)
253