blob: c4903d28634ceeb15805d469ca61dae35d90523f [file] [log] [blame]
// Copyright 2016 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 <lib/syscalls/forward.h>
#include <trace.h>
#include <zircon/errors.h>
#include <zircon/rights.h>
#include <zircon/syscalls-next.h>
#include <zircon/syscalls/object.h>
#include <zircon/types.h>
#include <fbl/ref_ptr.h>
#include <object/dispatcher.h>
#include <object/job_dispatcher.h>
#include <object/process_dispatcher.h>
#define LOCAL_TRACE 0
// zx_status_t zx_object_signal
zx_status_t sys_object_signal(zx_handle_t handle_value, uint32_t clear_mask, uint32_t set_mask) {
LTRACEF("handle %x\n", handle_value);
auto up = ProcessDispatcher::GetCurrent();
fbl::RefPtr<Dispatcher> dispatcher;
auto status =
up->handle_table().GetDispatcherWithRights(*up, handle_value, ZX_RIGHT_SIGNAL, &dispatcher);
if (status != ZX_OK)
return status;
return dispatcher->user_signal_self(clear_mask, set_mask);
}
// zx_status_t zx_object_signal_peer
zx_status_t sys_object_signal_peer(zx_handle_t handle_value, uint32_t clear_mask,
uint32_t set_mask) {
LTRACEF("handle %x\n", handle_value);
auto up = ProcessDispatcher::GetCurrent();
fbl::RefPtr<Dispatcher> dispatcher;
auto status = up->handle_table().GetDispatcherWithRights(*up, handle_value, ZX_RIGHT_SIGNAL_PEER,
&dispatcher);
if (status != ZX_OK)
return status;
return dispatcher->user_signal_peer(clear_mask, set_mask);
}
// Given a kernel object with children objects, obtain a handle to the
// child specified by the provided kernel object id.
// zx_status_t zx_object_get_child
zx_status_t sys_object_get_child(zx_handle_t handle, uint64_t koid, zx_rights_t rights,
zx_handle_t* out) {
auto up = ProcessDispatcher::GetCurrent();
fbl::RefPtr<Dispatcher> dispatcher;
uint32_t parent_rights;
auto status = up->handle_table().GetDispatcherAndRights(*up, handle, &dispatcher, &parent_rights);
if (status != ZX_OK)
return status;
if (!(parent_rights & ZX_RIGHT_ENUMERATE))
return ZX_ERR_ACCESS_DENIED;
if (rights == ZX_RIGHT_SAME_RIGHTS) {
rights = parent_rights;
} else if ((parent_rights & rights) != rights) {
return ZX_ERR_ACCESS_DENIED;
}
// TODO(https://fxbug.dev/42175105): Constructing the handles below may cause the handle count to
// go from 0->1, resulting in multiple on_zero_handles invocations. Presently this is benign,
// except for one scenario with processes in the initial state. Such processes are filtered out by
// the SimpleJobEnumerator and should not be able to be learned about. Further protection against
// guessing is not performed here since the worst case scenario is a misbehaving privileged
// process guessing a koid and destroying a process that was in construction.
auto process = DownCastDispatcher<ProcessDispatcher>(&dispatcher);
if (process) {
auto thread = process->LookupThreadById(koid);
if (!thread)
return ZX_ERR_NOT_FOUND;
return up->MakeAndAddHandle(ktl::move(thread), rights, out);
}
auto job = DownCastDispatcher<JobDispatcher>(&dispatcher);
if (job) {
auto child = job->LookupJobById(koid);
if (child)
return up->MakeAndAddHandle(ktl::move(child), rights, out);
auto proc = job->LookupProcessById(koid);
if (proc) {
return up->MakeAndAddHandle(ktl::move(proc), rights, out);
}
return ZX_ERR_NOT_FOUND;
}
return ZX_ERR_WRONG_TYPE;
}