blob: b004a9657d28227d4aad85308035e28806b3eddd [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#include <fbl/ref_ptr.h>
#include <lib/user_copy/user_ptr.h>
#include <object/process_dispatcher.h>
#include <zircon/types.h>
// Extracts the handles that would be consumed on syscalls with handle_release semantics
// from |offset| to |offset + chunk_size| from |user_handles| and returns them
// in |handles| which must be at of at least size |chunk_size|.
zx_status_t get_user_handles_to_consume(
user_in_ptr<const zx_handle_t> user_handles, size_t offset, size_t chunk_size,
zx_handle_t* handles);
zx_status_t get_user_handles_to_consume(
user_inout_ptr<zx_handle_disposition_t> user_handles, size_t offset, size_t chunk_size,
zx_handle_t* handles);
// Removes the handles pointed by |user_handles| from |process|. Returns ZX_OK if all handles
// have been removed, error otherwise. It only stops early if get_user_handles() fails.
template <typename T>
zx_status_t RemoveUserHandles(
T user_handles, size_t num_handles, ProcessDispatcher* process) {
zx_handle_t handles[kMaxMessageHandles];
size_t offset = 0u;
zx_status_t status = ZX_OK;
while (offset < num_handles) {
// We process |num_handles| in chunks of |kMaxMessageHandles| because we don't have
// a limit on how large |num_handles| can be.
auto chunk_size = fbl::min<size_t>(num_handles - offset, kMaxMessageHandles);
status = get_user_handles_to_consume(user_handles, offset, chunk_size, handles);
if (status != ZX_OK) {
break;
}
status = process->RemoveHandles(handles, chunk_size);
offset += chunk_size;
}
return status;
}
// Given |handle| it returns a |raw_handle| that should be sent over |channel|. In case
// of error, the return value should be reflected back to the user.
zx_status_t get_handle_for_message_locked(
ProcessDispatcher* process, const Dispatcher* channel,
zx_handle_t handle_val, Handle** raw_handle)
TA_REQ(process->handle_table_lock());
zx_status_t get_handle_for_message_locked(
ProcessDispatcher* process, const Dispatcher* channel,
zx_handle_disposition_t handle_disposition, Handle** raw_handle)
TA_REQ(process->handle_table_lock());