1 // Copyright 2018 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 
6 #include <limits>
7 #include <stdalign.h>
8 #include <stdint.h>
9 #include <stdlib.h>
10 
11 #include <lib/fidl/coding.h>
12 
13 #ifdef __Fuchsia__
14 
15 #include <lib/fidl/internal.h>
16 #include <zircon/assert.h>
17 #include <zircon/compiler.h>
18 #include <zircon/syscalls.h>
19 
20 #include "buffer_walker.h"
21 
22 namespace {
23 
24 class FidlHandleCloser final : public fidl::internal::BufferWalker<FidlHandleCloser, true, true> {
25     typedef fidl::internal::BufferWalker<FidlHandleCloser, true, true> Super;
26 
27 public:
FidlHandleCloser(const fidl_type_t * type,void * bytes,uint32_t num_bytes,const char ** out_error_msg)28     FidlHandleCloser(const fidl_type_t* type, void* bytes, uint32_t num_bytes,
29                      const char** out_error_msg)
30         : Super(type), bytes_(static_cast<uint8_t*>(bytes)), num_bytes_(num_bytes),
31           out_error_msg_(out_error_msg) {}
32 
Walk()33     void Walk() {
34         Super::Walk();
35     }
36 
bytes() const37     uint8_t* bytes() const { return bytes_; }
num_bytes() const38     uint32_t num_bytes() const { return num_bytes_; }
num_handles() const39     uint32_t num_handles() const { return std::numeric_limits<uint32_t>::max(); }
40 
ValidateOutOfLineStorageClaim(const void * a,void * b)41     bool ValidateOutOfLineStorageClaim(const void* a, void* b) {
42         return true;
43     }
44 
UnclaimedHandle(zx_handle_t * out_handle)45     void UnclaimedHandle(zx_handle_t* out_handle) {
46         // This will never happen since we are returning numeric_limits::max() in num_handles.
47         // We want to claim (close) all the handles.
48         ZX_DEBUG_ASSERT(false);
49     }
50 
ClaimedHandle(zx_handle_t * out_handle,uint32_t idx)51     void ClaimedHandle(zx_handle_t* out_handle, uint32_t idx) {
52         if (*out_handle != ZX_HANDLE_INVALID) {
53             zx_handle_close(*out_handle);
54         }
55         *out_handle = ZX_HANDLE_INVALID;
56     }
57 
58     template <class T>
UpdatePointer(T * const * p,T * v)59     void UpdatePointer(T* const* p, T* v) {}
60 
GetPointerState(const void * ptr) const61     PointerState GetPointerState(const void* ptr) const {
62         return *static_cast<const uintptr_t*>(ptr) == 0
63                ? PointerState::ABSENT
64                : PointerState::PRESENT;
65     }
66 
GetHandleState(zx_handle_t p) const67     HandleState GetHandleState(zx_handle_t p) const {
68         // Treat all handles as present to keep the buffer walker going.
69         return HandleState::PRESENT;
70     }
71 
SetError(const char * error_msg)72     void SetError(const char* error_msg) {
73         status_ = ZX_ERR_INVALID_ARGS;
74         if (out_error_msg_ != nullptr) {
75             *out_error_msg_ = error_msg;
76         }
77     }
78 
status() const79     zx_status_t status() const { return status_; }
80 
81 private:
82     // Message state passed in to the constructor.
83     uint8_t* const bytes_;
84     const uint32_t num_bytes_;
85     const char** const out_error_msg_;
86     zx_status_t status_ = ZX_OK;
87 };
88 
89 } // namespace
90 
91 #endif  // __Fuchsia__
92 
fidl_close_handles(const fidl_type_t * type,void * bytes,uint32_t num_bytes,const char ** out_error_msg)93 zx_status_t fidl_close_handles(const fidl_type_t* type, void* bytes, uint32_t num_bytes,
94                                const char** out_error_msg) {
95 #if __Fuchsia__
96     FidlHandleCloser handle_closer(type, bytes, num_bytes, out_error_msg);
97     handle_closer.Walk();
98     return handle_closer.status();
99 #else
100     return ZX_OK;  // there can't be any handles on the host
101 #endif
102 }
103 
fidl_close_handles_msg(const fidl_type_t * type,const fidl_msg_t * msg,const char ** out_error_msg)104 zx_status_t fidl_close_handles_msg(const fidl_type_t* type, const fidl_msg_t* msg,
105                                    const char** out_error_msg) {
106     return fidl_close_handles(type, msg->bytes, msg->num_bytes, out_error_msg);
107 }
108 
109