[Zion] Add the ability to pass capabilities via endpoint call.

This commit is contained in:
Drew Galbraith 2023-10-24 23:32:05 -07:00
parent 5b781bb394
commit b516087922
18 changed files with 218 additions and 131 deletions

View file

@ -4,8 +4,8 @@
#include "scheduler/scheduler.h"
z_err_t UnboundedMessageQueue::PushBack(uint64_t num_bytes, const void* bytes,
uint64_t num_caps,
const z_cap_t* caps) {
uint64_t num_caps, const z_cap_t* caps,
z_cap_t reply_cap) {
if (num_bytes > 0x1000) {
dbgln("Large message size unimplemented: %x", num_bytes);
return glcr::UNIMPLEMENTED;
@ -18,6 +18,12 @@ z_err_t UnboundedMessageQueue::PushBack(uint64_t num_bytes, const void* bytes,
message->bytes[i] = static_cast<const uint8_t*>(bytes)[i];
}
if (reply_cap != kZionInvalidCapability) {
// FIXME: We're just trusting that capability has the correct permissions.
message->reply_cap =
gScheduler->CurrentProcess().ReleaseCapability(reply_cap);
}
for (uint64_t i = 0; i < num_caps; i++) {
// FIXME: This would feel safer closer to the relevant syscall.
// FIXME: Race conditions on get->check->release here. Would be better to
@ -46,7 +52,8 @@ z_err_t UnboundedMessageQueue::PushBack(uint64_t num_bytes, const void* bytes,
}
z_err_t UnboundedMessageQueue::PopFront(uint64_t* num_bytes, void* bytes,
uint64_t* num_caps, z_cap_t* caps) {
uint64_t* num_caps, z_cap_t* caps,
z_cap_t* reply_cap) {
mutex_.Lock();
while (pending_messages_.empty()) {
auto thread = gScheduler->CurrentThread();
@ -75,8 +82,16 @@ z_err_t UnboundedMessageQueue::PopFront(uint64_t* num_bytes, void* bytes,
static_cast<uint8_t*>(bytes)[i] = next_msg->bytes[i];
}
*num_caps = next_msg->caps.size();
auto& proc = gScheduler->CurrentProcess();
if (reply_cap != nullptr) {
if (!next_msg->reply_cap) {
dbgln("Tried to read reply capability off of a message without one");
return glcr::INTERNAL;
}
*reply_cap = proc.AddExistingCapability(next_msg->reply_cap);
}
*num_caps = next_msg->caps.size();
for (uint64_t i = 0; i < *num_caps; i++) {
caps[i] = proc.AddExistingCapability(next_msg->caps.PopFront());
}
@ -102,7 +117,8 @@ void UnboundedMessageQueue::WriteKernel(uint64_t init,
glcr::ErrorCode SingleMessageQueue::PushBack(uint64_t num_bytes,
const void* bytes,
uint64_t num_caps,
const z_cap_t* caps) {
const z_cap_t* caps,
z_cap_t reply_port) {
MutexHolder h(mutex_);
if (has_written_) {
return glcr::FAILED_PRECONDITION;
@ -114,6 +130,11 @@ glcr::ErrorCode SingleMessageQueue::PushBack(uint64_t num_bytes,
bytes_[i] = reinterpret_cast<const uint8_t*>(bytes)[i];
}
if (reply_port != kZionInvalidCapability) {
dbgln("Sent a reply port to a single message queue");
return glcr::INTERNAL;
}
for (uint64_t i = 0; i < num_caps; i++) {
// FIXME: This would feel safer closer to the relevant syscall.
auto cap = gScheduler->CurrentProcess().GetCapability(caps[i]);
@ -139,8 +160,8 @@ glcr::ErrorCode SingleMessageQueue::PushBack(uint64_t num_bytes,
}
glcr::ErrorCode SingleMessageQueue::PopFront(uint64_t* num_bytes, void* bytes,
uint64_t* num_caps,
z_cap_t* caps) {
uint64_t* num_caps, z_cap_t* caps,
z_cap_t* reply_port) {
mutex_.Lock();
while (!has_written_) {
auto thread = gScheduler->CurrentThread();
@ -169,6 +190,11 @@ glcr::ErrorCode SingleMessageQueue::PopFront(uint64_t* num_bytes, void* bytes,
reinterpret_cast<uint8_t*>(bytes)[i] = bytes_[i];
}
if (reply_port != nullptr) {
dbgln("Tried to read a reply port a single message queue");
return glcr::INTERNAL;
}
*num_caps = caps_.size();
auto& proc = gScheduler->CurrentProcess();
for (uint64_t i = 0; i < *num_caps; i++) {

View file

@ -15,9 +15,11 @@ class MessageQueue {
virtual ~MessageQueue() {}
virtual glcr::ErrorCode PushBack(uint64_t num_bytes, const void* bytes,
uint64_t num_caps, const z_cap_t* caps) = 0;
uint64_t num_caps, const z_cap_t* caps,
z_cap_t reply_cap = 0) = 0;
virtual glcr::ErrorCode PopFront(uint64_t* num_bytes, void* bytes,
uint64_t* num_caps, z_cap_t* caps) = 0;
uint64_t* num_caps, z_cap_t* caps,
z_cap_t* reply_cap = nullptr) = 0;
virtual bool empty() = 0;
protected:
@ -35,9 +37,10 @@ class UnboundedMessageQueue : public MessageQueue {
virtual ~UnboundedMessageQueue() override {}
glcr::ErrorCode PushBack(uint64_t num_bytes, const void* bytes,
uint64_t num_caps, const z_cap_t* caps) override;
uint64_t num_caps, const z_cap_t* caps,
z_cap_t reply_cap) override;
glcr::ErrorCode PopFront(uint64_t* num_bytes, void* bytes, uint64_t* num_caps,
z_cap_t* caps) override;
z_cap_t* caps, z_cap_t* reply_cap) override;
void WriteKernel(uint64_t init, glcr::RefPtr<Capability> cap);
@ -52,6 +55,7 @@ class UnboundedMessageQueue : public MessageQueue {
uint8_t* bytes;
glcr::LinkedList<glcr::RefPtr<Capability>> caps;
glcr::RefPtr<Capability> reply_cap;
};
glcr::LinkedList<glcr::SharedPtr<Message>> pending_messages_;
@ -65,9 +69,10 @@ class SingleMessageQueue : public MessageQueue {
virtual ~SingleMessageQueue() override {}
glcr::ErrorCode PushBack(uint64_t num_bytes, const void* bytes,
uint64_t num_caps, const z_cap_t* caps) override;
uint64_t num_caps, const z_cap_t* caps,
z_cap_t reply_cap) override;
glcr::ErrorCode PopFront(uint64_t* num_bytes, void* bytes, uint64_t* num_caps,
z_cap_t* caps) override;
z_cap_t* caps, z_cap_t* reply_cap) override;
bool empty() override {
MutexHolder h(mutex_);