[zion] Move capability validation to capability.h
This commit is contained in:
parent
93cf8f2740
commit
172bf51db7
|
@ -20,6 +20,8 @@ class Capability : public RefCounted<Capability> {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
RefPtr<T> obj();
|
RefPtr<T> obj();
|
||||||
|
|
||||||
|
RefPtr<KernelObject> raw_obj() { return obj_; }
|
||||||
|
|
||||||
uint64_t permissions() { return permissions_; }
|
uint64_t permissions() { return permissions_; }
|
||||||
bool HasPermissions(uint64_t requested) {
|
bool HasPermissions(uint64_t requested) {
|
||||||
return (permissions_ & requested) == requested;
|
return (permissions_ & requested) == requested;
|
||||||
|
@ -37,3 +39,28 @@ RefPtr<T> Capability::obj() {
|
||||||
}
|
}
|
||||||
return StaticCastRefPtr<T>(obj_);
|
return StaticCastRefPtr<T>(obj_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
z_err_t ValidateCapability(const RefPtr<Capability>& cap,
|
||||||
|
uint64_t permissions) {
|
||||||
|
if (!cap) {
|
||||||
|
return Z_ERR_CAP_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cap->raw_obj()->TypeTag() != KernelObjectTag<T>::type) {
|
||||||
|
return Z_ERR_CAP_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cap->HasPermissions(permissions)) {
|
||||||
|
return Z_ERR_CAP_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Z_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RET_IF_NULL(expr) \
|
||||||
|
{ \
|
||||||
|
if (!expr) { \
|
||||||
|
return Z_ERR_CAP_TYPE; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
|
@ -1,19 +1,17 @@
|
||||||
#include "syscall/address_space.h"
|
#include "syscall/address_space.h"
|
||||||
|
|
||||||
|
#include "capability/capability.h"
|
||||||
#include "scheduler/scheduler.h"
|
#include "scheduler/scheduler.h"
|
||||||
#include "syscall/syscall.h"
|
|
||||||
|
|
||||||
z_err_t AddressSpaceMap(ZAddressSpaceMapReq* req) {
|
z_err_t AddressSpaceMap(ZAddressSpaceMapReq* req) {
|
||||||
auto& curr_proc = gScheduler->CurrentProcess();
|
auto& curr_proc = gScheduler->CurrentProcess();
|
||||||
auto vmas_cap = curr_proc.GetCapability(req->vmas_cap);
|
auto vmas_cap = curr_proc.GetCapability(req->vmas_cap);
|
||||||
auto vmmo_cap = curr_proc.GetCapability(req->vmmo_cap);
|
auto vmmo_cap = curr_proc.GetCapability(req->vmmo_cap);
|
||||||
RET_ERR(ValidateCap(vmas_cap, ZC_WRITE));
|
RET_ERR(ValidateCapability<AddressSpace>(vmas_cap, ZC_WRITE));
|
||||||
RET_ERR(ValidateCap(vmmo_cap, ZC_WRITE));
|
RET_ERR(ValidateCapability<MemoryObject>(vmmo_cap, ZC_WRITE));
|
||||||
|
|
||||||
auto vmas = vmas_cap->obj<AddressSpace>();
|
auto vmas = vmas_cap->obj<AddressSpace>();
|
||||||
auto vmmo = vmmo_cap->obj<MemoryObject>();
|
auto vmmo = vmmo_cap->obj<MemoryObject>();
|
||||||
RET_IF_NULL(vmas);
|
|
||||||
RET_IF_NULL(vmmo);
|
|
||||||
|
|
||||||
// FIXME: Validation necessary.
|
// FIXME: Validation necessary.
|
||||||
if (req->vmas_offset != 0) {
|
if (req->vmas_offset != 0) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "syscall/channel.h"
|
#include "syscall/channel.h"
|
||||||
|
|
||||||
|
#include "capability/capability.h"
|
||||||
#include "scheduler/scheduler.h"
|
#include "scheduler/scheduler.h"
|
||||||
#include "syscall/syscall.h"
|
|
||||||
|
|
||||||
z_err_t ChannelCreate(ZChannelCreateReq* req) {
|
z_err_t ChannelCreate(ZChannelCreateReq* req) {
|
||||||
auto& proc = gScheduler->CurrentProcess();
|
auto& proc = gScheduler->CurrentProcess();
|
||||||
|
@ -15,19 +15,17 @@ z_err_t ChannelCreate(ZChannelCreateReq* req) {
|
||||||
z_err_t ChannelSend(ZChannelSendReq* req) {
|
z_err_t ChannelSend(ZChannelSendReq* req) {
|
||||||
auto& proc = gScheduler->CurrentProcess();
|
auto& proc = gScheduler->CurrentProcess();
|
||||||
auto chan_cap = proc.GetCapability(req->chan_cap);
|
auto chan_cap = proc.GetCapability(req->chan_cap);
|
||||||
RET_ERR(ValidateCap(chan_cap, ZC_WRITE));
|
RET_ERR(ValidateCapability<Channel>(chan_cap, ZC_WRITE));
|
||||||
|
|
||||||
auto chan = chan_cap->obj<Channel>();
|
auto chan = chan_cap->obj<Channel>();
|
||||||
RET_IF_NULL(chan);
|
|
||||||
return chan->Write(req->num_bytes, req->data, req->num_caps, req->caps);
|
return chan->Write(req->num_bytes, req->data, req->num_caps, req->caps);
|
||||||
}
|
}
|
||||||
|
|
||||||
z_err_t ChannelRecv(ZChannelRecvReq* req) {
|
z_err_t ChannelRecv(ZChannelRecvReq* req) {
|
||||||
auto& proc = gScheduler->CurrentProcess();
|
auto& proc = gScheduler->CurrentProcess();
|
||||||
auto chan_cap = proc.GetCapability(req->chan_cap);
|
auto chan_cap = proc.GetCapability(req->chan_cap);
|
||||||
RET_ERR(ValidateCap(chan_cap, ZC_READ));
|
RET_ERR(ValidateCapability<Channel>(chan_cap, ZC_READ));
|
||||||
|
|
||||||
auto chan = chan_cap->obj<Channel>();
|
auto chan = chan_cap->obj<Channel>();
|
||||||
RET_IF_NULL(chan);
|
|
||||||
return chan->Read(req->num_bytes, req->data, req->num_caps, req->caps);
|
return chan->Read(req->num_bytes, req->data, req->num_caps, req->caps);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include "syscall/port.h"
|
#include "syscall/port.h"
|
||||||
|
|
||||||
|
#include "capability/capability.h"
|
||||||
#include "interrupt/interrupt.h"
|
#include "interrupt/interrupt.h"
|
||||||
#include "scheduler/scheduler.h"
|
#include "scheduler/scheduler.h"
|
||||||
#include "syscall/syscall.h"
|
|
||||||
|
|
||||||
z_err_t PortCreate(ZPortCreateReq* req) {
|
z_err_t PortCreate(ZPortCreateReq* req) {
|
||||||
auto& proc = gScheduler->CurrentProcess();
|
auto& proc = gScheduler->CurrentProcess();
|
||||||
|
@ -14,20 +14,18 @@ z_err_t PortCreate(ZPortCreateReq* req) {
|
||||||
z_err_t PortSend(ZPortSendReq* req) {
|
z_err_t PortSend(ZPortSendReq* req) {
|
||||||
auto& proc = gScheduler->CurrentProcess();
|
auto& proc = gScheduler->CurrentProcess();
|
||||||
auto port_cap = proc.GetCapability(req->port_cap);
|
auto port_cap = proc.GetCapability(req->port_cap);
|
||||||
RET_ERR(ValidateCap(port_cap, ZC_WRITE));
|
RET_ERR(ValidateCapability<Port>(port_cap, ZC_WRITE));
|
||||||
|
|
||||||
auto port = port_cap->obj<Port>();
|
auto port = port_cap->obj<Port>();
|
||||||
RET_IF_NULL(port);
|
|
||||||
return port->Write(req->num_bytes, req->data, req->num_caps, req->caps);
|
return port->Write(req->num_bytes, req->data, req->num_caps, req->caps);
|
||||||
}
|
}
|
||||||
|
|
||||||
z_err_t PortRecv(ZPortRecvReq* req) {
|
z_err_t PortRecv(ZPortRecvReq* req) {
|
||||||
auto& proc = gScheduler->CurrentProcess();
|
auto& proc = gScheduler->CurrentProcess();
|
||||||
auto port_cap = proc.GetCapability(req->port_cap);
|
auto port_cap = proc.GetCapability(req->port_cap);
|
||||||
RET_ERR(ValidateCap(port_cap, ZC_READ));
|
RET_ERR(ValidateCapability<Port>(port_cap, ZC_READ));
|
||||||
|
|
||||||
auto port = port_cap->obj<Port>();
|
auto port = port_cap->obj<Port>();
|
||||||
RET_IF_NULL(port);
|
|
||||||
ZMessage message{
|
ZMessage message{
|
||||||
.num_bytes = *req->num_bytes,
|
.num_bytes = *req->num_bytes,
|
||||||
.data = const_cast<void*>(req->data),
|
.data = const_cast<void*>(req->data),
|
||||||
|
@ -40,10 +38,9 @@ z_err_t PortRecv(ZPortRecvReq* req) {
|
||||||
z_err_t PortPoll(ZPortPollReq* req) {
|
z_err_t PortPoll(ZPortPollReq* req) {
|
||||||
auto& proc = gScheduler->CurrentProcess();
|
auto& proc = gScheduler->CurrentProcess();
|
||||||
auto port_cap = proc.GetCapability(req->port_cap);
|
auto port_cap = proc.GetCapability(req->port_cap);
|
||||||
RET_ERR(ValidateCap(port_cap, ZC_READ));
|
RET_ERR(ValidateCapability<Port>(port_cap, ZC_READ));
|
||||||
|
|
||||||
auto port = port_cap->obj<Port>();
|
auto port = port_cap->obj<Port>();
|
||||||
RET_IF_NULL(port);
|
|
||||||
// FIXME: Race condition here where this call could block if the last message
|
// FIXME: Race condition here where this call could block if the last message
|
||||||
// is removed between this check and the port read.
|
// is removed between this check and the port read.
|
||||||
if (!port->HasMessages()) {
|
if (!port->HasMessages()) {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include "syscall/process.h"
|
#include "syscall/process.h"
|
||||||
|
|
||||||
|
#include "capability/capability.h"
|
||||||
#include "scheduler/process_manager.h"
|
#include "scheduler/process_manager.h"
|
||||||
#include "scheduler/scheduler.h"
|
#include "scheduler/scheduler.h"
|
||||||
#include "syscall/syscall.h"
|
|
||||||
|
|
||||||
z_err_t ProcessExit(ZProcessExitReq* req) {
|
z_err_t ProcessExit(ZProcessExitReq* req) {
|
||||||
auto curr_thread = gScheduler->CurrentThread();
|
auto curr_thread = gScheduler->CurrentThread();
|
||||||
|
@ -16,7 +16,7 @@ z_err_t ProcessExit(ZProcessExitReq* req) {
|
||||||
z_err_t ProcessSpawn(ZProcessSpawnReq* req) {
|
z_err_t ProcessSpawn(ZProcessSpawnReq* req) {
|
||||||
auto& curr_proc = gScheduler->CurrentProcess();
|
auto& curr_proc = gScheduler->CurrentProcess();
|
||||||
auto cap = curr_proc.GetCapability(req->proc_cap);
|
auto cap = curr_proc.GetCapability(req->proc_cap);
|
||||||
RET_ERR(ValidateCap(cap, ZC_PROC_SPAWN_PROC));
|
RET_ERR(ValidateCapability<Process>(cap, ZC_PROC_SPAWN_PROC));
|
||||||
|
|
||||||
RefPtr<Process> proc = Process::Create();
|
RefPtr<Process> proc = Process::Create();
|
||||||
gProcMan->InsertProcess(proc);
|
gProcMan->InsertProcess(proc);
|
||||||
|
|
|
@ -43,19 +43,6 @@ void InitSyscall() {
|
||||||
SetMSR(LSTAR, reinterpret_cast<uint64_t>(syscall_enter));
|
SetMSR(LSTAR, reinterpret_cast<uint64_t>(syscall_enter));
|
||||||
}
|
}
|
||||||
|
|
||||||
z_err_t ValidateCap(const RefPtr<Capability>& cap, uint64_t permissions) {
|
|
||||||
if (!cap) {
|
|
||||||
return Z_ERR_CAP_NOT_FOUND;
|
|
||||||
}
|
|
||||||
// FIXME: Check capability type before permissions, otherwise you can
|
|
||||||
// get a confusing error.
|
|
||||||
if (!cap->HasPermissions(permissions)) {
|
|
||||||
dbgln("PERM, has %x needs %x", cap->permissions(), permissions);
|
|
||||||
return Z_ERR_CAP_DENIED;
|
|
||||||
}
|
|
||||||
return Z_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define CASE(name) \
|
#define CASE(name) \
|
||||||
case kZion##name: \
|
case kZion##name: \
|
||||||
return name(reinterpret_cast<Z##name##Req*>(req));
|
return name(reinterpret_cast<Z##name##Req*>(req));
|
||||||
|
|
|
@ -4,13 +4,3 @@
|
||||||
#include "include/ztypes.h"
|
#include "include/ztypes.h"
|
||||||
|
|
||||||
void InitSyscall();
|
void InitSyscall();
|
||||||
|
|
||||||
// FIXME: This probably belongs in capability.h
|
|
||||||
z_err_t ValidateCap(const RefPtr<Capability>& cap, uint64_t permissions);
|
|
||||||
|
|
||||||
#define RET_IF_NULL(expr) \
|
|
||||||
{ \
|
|
||||||
if (!expr) { \
|
|
||||||
return Z_ERR_CAP_TYPE; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
#include "syscall/thread.h"
|
#include "syscall/thread.h"
|
||||||
|
|
||||||
|
#include "capability/capability.h"
|
||||||
#include "scheduler/scheduler.h"
|
#include "scheduler/scheduler.h"
|
||||||
#include "syscall/syscall.h"
|
|
||||||
|
|
||||||
z_err_t ThreadCreate(ZThreadCreateReq* req) {
|
z_err_t ThreadCreate(ZThreadCreateReq* req) {
|
||||||
auto& curr_proc = gScheduler->CurrentProcess();
|
auto& curr_proc = gScheduler->CurrentProcess();
|
||||||
auto cap = curr_proc.GetCapability(req->proc_cap);
|
auto cap = curr_proc.GetCapability(req->proc_cap);
|
||||||
RET_ERR(ValidateCap(cap, ZC_PROC_SPAWN_THREAD));
|
RET_ERR(ValidateCapability<Process>(cap, ZC_PROC_SPAWN_THREAD));
|
||||||
|
|
||||||
auto parent_proc = cap->obj<Process>();
|
auto parent_proc = cap->obj<Process>();
|
||||||
RET_IF_NULL(parent_proc);
|
|
||||||
auto thread = parent_proc->CreateThread();
|
auto thread = parent_proc->CreateThread();
|
||||||
*req->thread_cap = curr_proc.AddNewCapability(thread, ZC_WRITE);
|
*req->thread_cap = curr_proc.AddNewCapability(thread, ZC_WRITE);
|
||||||
return Z_OK;
|
return Z_OK;
|
||||||
|
@ -18,10 +17,9 @@ z_err_t ThreadCreate(ZThreadCreateReq* req) {
|
||||||
z_err_t ThreadStart(ZThreadStartReq* req) {
|
z_err_t ThreadStart(ZThreadStartReq* req) {
|
||||||
auto& curr_proc = gScheduler->CurrentProcess();
|
auto& curr_proc = gScheduler->CurrentProcess();
|
||||||
auto cap = curr_proc.GetCapability(req->thread_cap);
|
auto cap = curr_proc.GetCapability(req->thread_cap);
|
||||||
RET_ERR(ValidateCap(cap, ZC_WRITE));
|
RET_ERR(ValidateCapability<Thread>(cap, ZC_WRITE));
|
||||||
|
|
||||||
auto thread = cap->obj<Thread>();
|
auto thread = cap->obj<Thread>();
|
||||||
RET_IF_NULL(thread);
|
|
||||||
// FIXME: validate entry point is in user space.
|
// FIXME: validate entry point is in user space.
|
||||||
thread->Start(req->entry, req->arg1, req->arg2);
|
thread->Start(req->entry, req->arg1, req->arg2);
|
||||||
return Z_OK;
|
return Z_OK;
|
||||||
|
|
Loading…
Reference in New Issue