// Copyright 2018 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 <limits> #include <stdalign.h> #include <stdint.h> #include <stdlib.h> #include <lib/fidl/coding.h> #ifdef __Fuchsia__ #include <lib/fidl/internal.h> #include <zircon/assert.h> #include <zircon/compiler.h> #include <zircon/syscalls.h> #include "buffer_walker.h" namespace { class FidlHandleCloser final : public fidl::internal::BufferWalker<FidlHandleCloser, true, true> { typedef fidl::internal::BufferWalker<FidlHandleCloser, true, true> Super; public: FidlHandleCloser(const fidl_type_t* type, void* bytes, uint32_t num_bytes, const char** out_error_msg) : Super(type), bytes_(static_cast<uint8_t*>(bytes)), num_bytes_(num_bytes), out_error_msg_(out_error_msg) {} void Walk() { Super::Walk(); } uint8_t* bytes() const { return bytes_; } uint32_t num_bytes() const { return num_bytes_; } uint32_t num_handles() const { return std::numeric_limits<uint32_t>::max(); } bool ValidateOutOfLineStorageClaim(const void* a, void* b) { return true; } void UnclaimedHandle(zx_handle_t* out_handle) { // This will never happen since we are returning numeric_limits::max() in num_handles. // We want to claim (close) all the handles. ZX_DEBUG_ASSERT(false); } void ClaimedHandle(zx_handle_t* out_handle, uint32_t idx) { if (*out_handle != ZX_HANDLE_INVALID) { zx_handle_close(*out_handle); } *out_handle = ZX_HANDLE_INVALID; } template <class T> void UpdatePointer(T* const* p, T* v) {} PointerState GetPointerState(const void* ptr) const { return *static_cast<const uintptr_t*>(ptr) == 0 ? PointerState::ABSENT : PointerState::PRESENT; } HandleState GetHandleState(zx_handle_t p) const { // Treat all handles as present to keep the buffer walker going. return HandleState::PRESENT; } void SetError(const char* error_msg) { status_ = ZX_ERR_INVALID_ARGS; if (out_error_msg_ != nullptr) { *out_error_msg_ = error_msg; } } zx_status_t status() const { return status_; } private: // Message state passed in to the constructor. uint8_t* const bytes_; const uint32_t num_bytes_; const char** const out_error_msg_; zx_status_t status_ = ZX_OK; }; } // namespace #endif // __Fuchsia__ zx_status_t fidl_close_handles(const fidl_type_t* type, void* bytes, uint32_t num_bytes, const char** out_error_msg) { #if __Fuchsia__ FidlHandleCloser handle_closer(type, bytes, num_bytes, out_error_msg); handle_closer.Walk(); return handle_closer.status(); #else return ZX_OK; // there can't be any handles on the host #endif } zx_status_t fidl_close_handles_msg(const fidl_type_t* type, const fidl_msg_t* msg, const char** out_error_msg) { return fidl_close_handles(type, msg->bytes, msg->num_bytes, out_error_msg); }