blob: 80b242f39bbcfd7e666bb4f4f5a043dabc860fc8 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <gtest/gtest.h>
#include "tools/fidlcat/interception_tests/interception_workflow_test.h"
namespace fidlcat {
// processargs_extract_handles tests.
// This function is the first to be intercepted. All the handles are defined.
std::unique_ptr<SystemCallTest> ProcessargsExtractHandles(
uint32_t nhandles, zx_handle_t handles[], uint32_t handle_info[], zx_handle_t* process_self,
zx_handle_t* job_default, zx_handle_t* vmar_root_self, zx_handle_t* thread_self) {
auto value = std::make_unique<SystemCallTest>("processargs_extract_handles", 0, "");
value->AddInput(nhandles);
value->AddInput(reinterpret_cast<uint64_t>(handles));
value->AddInput(reinterpret_cast<uint64_t>(handle_info));
value->AddInput(reinterpret_cast<uint64_t>(process_self));
value->AddInput(reinterpret_cast<uint64_t>(job_default));
value->AddInput(reinterpret_cast<uint64_t>(vmar_root_self));
value->AddInput(reinterpret_cast<uint64_t>(thread_self));
return value;
}
// Uses two sets of handles (one for each process).
// The same numerical value is used for a handle for both process.
// Check that each process has its own definition of the shared handle value.
#define PROCESSARGS_EXTRACT_HANDLES_TEST() \
constexpr uint32_t kDuplicatedHandleValue = 0x1e925427; \
constexpr uint32_t nhandles_1 = 12; \
zx_handle_t handles_1[nhandles_1] = {0x1e925427, 0xa45248f3, 0x18c254a3, 0x39b2565b, \
0x21c2485b, 0x37324bbb, 0x3b8255ab, 0x07b24b13, \
0x3dc2489b, 0x3a32566f, 0x38a2565f, 0x1842488f}; \
uint32_t handle_info_1[nhandles_1] = {0x00000001, 0x00000004, 0x00000002, 0x00000020, \
0x00010020, 0x00000003, 0x0000003b, 0x00000030, \
0x00010030, 0x00020030, 0x00000011, 0x00000013}; \
constexpr uint32_t nhandles_2 = 1; \
zx_handle_t handles_2[nhandles_2] = {0x1e925427}; \
uint32_t handle_info_2[nhandles_2] = {0x00010030}; \
zx_handle_t process_self; \
zx_handle_t job_default; \
zx_handle_t vmar_root_self; \
zx_handle_t thread_self; \
ProcessController controller(this, session(), loop()); \
PerformFunctionTest( \
&controller, "processargs_extract_handles", \
ProcessargsExtractHandles(nhandles_1, handles_1, handle_info_1, &process_self, &job_default, \
&vmar_root_self, &thread_self), \
kFirstPid, kFirstThreadKoid); \
PerformFunctionTest( \
&controller, "processargs_extract_handles", \
ProcessargsExtractHandles(nhandles_2, handles_2, handle_info_2, &process_self, &job_default, \
&vmar_root_self, &thread_self), \
kSecondPid, kSecondThreadKoid); \
SyscallDecoderDispatcher* dispatcher = controller.workflow().syscall_decoder_dispatcher(); \
ASSERT_EQ(dispatcher->inference().handle_size(kFirstPid), nhandles_1); \
const fidl_codec::semantic::InferredHandleInfo* info = \
dispatcher->inference().GetInferredHandleInfo(kFirstPid, kDuplicatedHandleValue); \
ASSERT_NE(info, nullptr); \
ASSERT_EQ(info->type(), "proc-self"); \
info = dispatcher->inference().GetInferredHandleInfo(kFirstPid, handles_1[8]); \
ASSERT_NE(info, nullptr); \
ASSERT_EQ(info->type(), "fd"); \
ASSERT_EQ(info->fd(), 1); \
\
ASSERT_EQ(dispatcher->inference().handle_size(kSecondPid), nhandles_2); \
info = dispatcher->inference().GetInferredHandleInfo(kSecondPid, kDuplicatedHandleValue); \
ASSERT_NE(info, nullptr); \
ASSERT_EQ(info->type(), "fd"); \
ASSERT_EQ(info->fd(), 1)
#define PROCESSARGS_EXTRACT_HANDLES_DISPLAY_TEST(name) \
TEST_F(InterceptionWorkflowTestX64, name) { PROCESSARGS_EXTRACT_HANDLES_TEST(); } \
TEST_F(InterceptionWorkflowTestArm, name) { PROCESSARGS_EXTRACT_HANDLES_TEST(); }
PROCESSARGS_EXTRACT_HANDLES_DISPLAY_TEST(ProcessargsExtractHandles)
// libc_extensions_init tests.
// This is the second intercepted function. Some handles have already been used by
// processargs_extract_handles and have been reset (null values).
std::unique_ptr<SystemCallTest> LibcExtensionsInit(uint32_t nhandles, zx_handle_t handles[],
uint32_t handle_info[], uint32_t name_count,
const char* names[]) {
auto value = std::make_unique<SystemCallTest>("libc_extensions_init", 0, "");
value->AddInput(nhandles);
value->AddInput(reinterpret_cast<uint64_t>(handles));
value->AddInput(reinterpret_cast<uint64_t>(handle_info));
value->AddInput(name_count);
value->AddInput(reinterpret_cast<uint64_t>(names));
return value;
}
#define LIBC_EXTENSIONS_INIT_TEST() \
constexpr uint32_t kMaxNameSize = 80; \
constexpr uint32_t nhandles = 12; \
constexpr uint32_t defined_handles = 8; \
zx_handle_t handles[nhandles] = {0x00000000, 0x00000000, 0x00000000, 0x39b2565b, \
0x21c2485b, 0x00000000, 0x3b8255ab, 0x07b24b13, \
0x3dc2489b, 0x3a32566f, 0x38a2565f, 0x1842488f}; \
uint32_t handle_info[nhandles] = {0x00000000, 0x00000000, 0x00000000, 0x00000020, \
0x00010020, 0x00000000, 0x0000003b, 0x00000030, \
0x00010030, 0x00020030, 0x00000011, 0x00000013}; \
constexpr uint32_t name_count = 2; \
char pkg[kMaxNameSize] = "/pkg"; \
char svc[kMaxNameSize] = "/svc"; \
const char* names[name_count] = {pkg, svc}; \
ProcessController controller(this, session(), loop()); \
PerformFunctionTest(&controller, "__libc_extensions_init", \
LibcExtensionsInit(nhandles, handles, handle_info, name_count, names), \
kFirstPid, kFirstThreadKoid); \
SyscallDecoderDispatcher* dispatcher = controller.workflow().syscall_decoder_dispatcher(); \
ASSERT_EQ(dispatcher->inference().handle_size(kFirstPid), defined_handles); \
ASSERT_EQ(dispatcher->inference().handle_size(kSecondPid), static_cast<size_t>(0)); \
const fidl_codec::semantic::InferredHandleInfo* info = \
dispatcher->inference().GetInferredHandleInfo(kFirstPid, handles[3]); \
ASSERT_NE(info, nullptr); \
ASSERT_EQ(info->type(), "dir"); \
ASSERT_EQ(info->path(), "/pkg")
#define LIBC_EXTENSIONS_INIT_DISPLAY_TEST(name) \
TEST_F(InterceptionWorkflowTestX64, name) { LIBC_EXTENSIONS_INIT_TEST(); } \
TEST_F(InterceptionWorkflowTestArm, name) { LIBC_EXTENSIONS_INIT_TEST(); }
LIBC_EXTENSIONS_INIT_DISPLAY_TEST(LibcExtensionsInit)
} // namespace fidlcat