[kernel] Make capabilities/handles global
Instead of handles / capabilities having numeric ids that are only valid for the owning process, they are now global in a system capabilities table. This will allow for specifying capabilities in IPC that doesn't need to be kernel-controlled. Processes will still need to be granted access to given capabilities, but that can become a simpler system call than the current method of sending them through mailbox messages (and worse, having to translate every one into a new capability like was the case before). In order to track which handles a process has access to, a new node_set based on node_map allows for an efficient storage and lookup of handles.
This commit is contained in:
@@ -9,7 +9,7 @@ using namespace obj;
|
||||
namespace syscalls {
|
||||
|
||||
j6_status_t
|
||||
handle_list(j6_handle_t *handles, size_t *handles_len)
|
||||
handle_list(j6_handle_descriptor *handles, size_t *handles_len)
|
||||
{
|
||||
process &p = process::current();
|
||||
size_t requested = *handles_len;
|
||||
@@ -23,12 +23,11 @@ handle_list(j6_handle_t *handles, size_t *handles_len)
|
||||
}
|
||||
|
||||
j6_status_t
|
||||
handle_clone(handle *orig, j6_handle_t *clone, uint32_t mask)
|
||||
handle_clone(j6_handle_t orig, j6_handle_t *clone, uint32_t mask)
|
||||
{
|
||||
*clone = g_cap_table.derive(orig, mask);
|
||||
process &p = process::current();
|
||||
*clone = p.add_handle(
|
||||
orig->object,
|
||||
orig->caps() & mask);
|
||||
p.add_handle(*clone);
|
||||
|
||||
return j6_status_ok;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <j6/types.h>
|
||||
|
||||
#include "capabilities.h"
|
||||
#include "objects/kobject.h"
|
||||
#include "objects/process.h"
|
||||
|
||||
@@ -12,41 +13,43 @@ namespace syscalls {
|
||||
template <typename T, typename... Args>
|
||||
T * construct_handle(j6_handle_t *id, Args... args)
|
||||
{
|
||||
obj::process &p = obj::process::current();
|
||||
T *o = new T {args...};
|
||||
*id = p.add_handle(o, T::creation_caps);
|
||||
*id = g_cap_table.create(o, T::creation_caps);
|
||||
|
||||
obj::process &p = obj::process::current();
|
||||
p.add_handle(*id);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
obj::handle * get_handle(j6_handle_t id)
|
||||
j6_status_t get_handle(j6_handle_t id, j6_cap_t caps, T *&object)
|
||||
{
|
||||
capability *capdata = g_cap_table.find(id);
|
||||
if (!capdata || capdata->type != T::type)
|
||||
return j6_err_invalid_arg;
|
||||
|
||||
obj::process &p = obj::process::current();
|
||||
obj::handle *h = p.lookup_handle(id);
|
||||
if (!h || h->type() != T::type)
|
||||
return nullptr;
|
||||
return h;
|
||||
if (!p.has_handle(id) || (capdata->caps & caps) != caps)
|
||||
return j6_err_denied;
|
||||
|
||||
object = static_cast<T*>(capdata->object);
|
||||
return j6_status_ok;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline obj::handle * get_handle<obj::kobject>(j6_handle_t id)
|
||||
inline j6_status_t get_handle<obj::kobject>(j6_handle_t id, j6_cap_t caps, obj::kobject *&object)
|
||||
{
|
||||
capability *capdata = g_cap_table.find(id);
|
||||
if (!capdata)
|
||||
return j6_err_invalid_arg;
|
||||
|
||||
obj::process &p = obj::process::current();
|
||||
return p.lookup_handle(id);
|
||||
if (!p.has_handle(id) || (capdata->caps & caps) != caps)
|
||||
return j6_err_denied;
|
||||
|
||||
object = capdata->object;
|
||||
return j6_status_ok;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T * remove_handle(j6_handle_t id)
|
||||
{
|
||||
obj::handle *h = get_handle<T>(id);
|
||||
T *o = nullptr;
|
||||
|
||||
if (h) {
|
||||
o = h->object;
|
||||
obj::process &p = obj::process::current();
|
||||
p.remove_handle(id);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace syscalls
|
||||
|
||||
@@ -31,30 +31,20 @@ j6_status_t
|
||||
prep_send(
|
||||
mailbox::message *msg,
|
||||
uint64_t tag,
|
||||
uint64_t badge,
|
||||
const void *data,
|
||||
size_t data_len,
|
||||
uint64_t subtag,
|
||||
const j6_handle_t *handles,
|
||||
size_t handle_count)
|
||||
{
|
||||
if (!msg ||
|
||||
data_len > mailbox::max_data_length ||
|
||||
handle_count > mailbox::max_handle_count)
|
||||
return j6_err_invalid_arg;
|
||||
|
||||
msg->tag = tag;
|
||||
msg->badge = badge;
|
||||
msg->subtag = subtag;
|
||||
|
||||
msg->handle_count = handle_count;
|
||||
for (unsigned i = 0; i < handle_count; ++i) {
|
||||
handle const *h = get_handle<kobject>(handles[i]);
|
||||
if (!h)
|
||||
return j6_err_invalid_arg;
|
||||
msg->handles[i] = *h;
|
||||
}
|
||||
memcpy(msg->handles, handles, sizeof(j6_handle_t) * handle_count);
|
||||
|
||||
msg->data_len = data_len;
|
||||
memcpy(msg->data, data, data_len);
|
||||
return j6_status_ok;
|
||||
}
|
||||
|
||||
@@ -62,43 +52,35 @@ void
|
||||
prep_receive(
|
||||
mailbox::message *msg,
|
||||
uint64_t *tag,
|
||||
uint64_t *badge,
|
||||
uint64_t *subtag,
|
||||
uint16_t *reply_tag,
|
||||
void *data,
|
||||
size_t *data_len,
|
||||
j6_handle_t *handles,
|
||||
size_t *handle_count)
|
||||
{
|
||||
if (tag) *tag = msg->tag;
|
||||
if (badge) *badge = msg->badge;
|
||||
if (subtag) *subtag = msg->subtag;
|
||||
if (reply_tag) *reply_tag = msg->reply_tag;
|
||||
|
||||
*data_len = msg->data_len;
|
||||
memcpy(data, msg->data, msg->data_len);
|
||||
|
||||
*handle_count = msg->handle_count;
|
||||
process &proc = process::current();
|
||||
for (size_t i = 0; i < msg->handle_count; ++i) {
|
||||
handles[i] = proc.add_handle(msg->handles[i]);
|
||||
msg->handles[i] = {};
|
||||
proc.add_handle(msg->handles[i]);
|
||||
handles[i] = msg->handles[i];
|
||||
}
|
||||
}
|
||||
|
||||
j6_status_t
|
||||
mailbox_send(
|
||||
handle *self_handle,
|
||||
mailbox *self,
|
||||
uint64_t tag,
|
||||
const void * data,
|
||||
size_t data_len,
|
||||
uint64_t subtag,
|
||||
j6_handle_t * handles,
|
||||
size_t handle_count)
|
||||
{
|
||||
mailbox *self = self_handle->as<mailbox>();
|
||||
mailbox::message *msg = new mailbox::message;
|
||||
|
||||
j6_status_t s = prep_send(msg,
|
||||
tag, self_handle->badge,
|
||||
data, data_len,
|
||||
tag, subtag,
|
||||
handles, handle_count);
|
||||
|
||||
if (s != j6_status_ok) {
|
||||
@@ -114,17 +96,14 @@ mailbox_send(
|
||||
j6_status_t
|
||||
mailbox_receive(
|
||||
mailbox *self,
|
||||
uint64_t * tag,
|
||||
void * data,
|
||||
size_t * data_len,
|
||||
j6_handle_t * handles,
|
||||
size_t * handle_count,
|
||||
uint16_t * reply_tag,
|
||||
uint64_t * badge,
|
||||
uint64_t *tag,
|
||||
uint64_t *subtag,
|
||||
j6_handle_t *handles,
|
||||
size_t *handle_count,
|
||||
uint16_t *reply_tag,
|
||||
uint64_t flags)
|
||||
{
|
||||
if (*data_len < mailbox::max_data_length ||
|
||||
*handle_count < mailbox::max_handle_count)
|
||||
if (*handle_count < mailbox::max_handle_count)
|
||||
return j6_err_insufficient;
|
||||
|
||||
mailbox::message *msg = nullptr;
|
||||
@@ -138,8 +117,7 @@ mailbox_receive(
|
||||
}
|
||||
|
||||
prep_receive(msg,
|
||||
tag, badge, reply_tag,
|
||||
data, data_len,
|
||||
tag, subtag, reply_tag,
|
||||
handles, handle_count);
|
||||
|
||||
if (*reply_tag == 0)
|
||||
@@ -150,19 +128,16 @@ mailbox_receive(
|
||||
|
||||
j6_status_t
|
||||
mailbox_call(
|
||||
handle *self_handle,
|
||||
uint64_t * tag,
|
||||
void * data,
|
||||
size_t * data_len,
|
||||
j6_handle_t * handles,
|
||||
size_t * handle_count)
|
||||
mailbox *self,
|
||||
uint64_t *tag,
|
||||
uint64_t *subtag,
|
||||
j6_handle_t *handles,
|
||||
size_t *handle_count)
|
||||
{
|
||||
mailbox *self = self_handle->as<mailbox>();
|
||||
mailbox::message *msg = new mailbox::message;
|
||||
|
||||
j6_status_t s = prep_send(msg,
|
||||
*tag, self_handle->badge,
|
||||
data, *data_len,
|
||||
*tag, *subtag,
|
||||
handles, *handle_count);
|
||||
|
||||
if (s != j6_status_ok) {
|
||||
@@ -177,8 +152,7 @@ mailbox_call(
|
||||
}
|
||||
|
||||
prep_receive(msg,
|
||||
tag, nullptr, nullptr,
|
||||
data, data_len,
|
||||
tag, subtag, 0,
|
||||
handles, handle_count);
|
||||
|
||||
delete msg;
|
||||
@@ -190,8 +164,7 @@ j6_status_t
|
||||
mailbox_respond(
|
||||
mailbox *self,
|
||||
uint64_t tag,
|
||||
const void * data,
|
||||
size_t data_len,
|
||||
uint64_t subtag,
|
||||
j6_handle_t * handles,
|
||||
size_t handle_count,
|
||||
uint16_t reply_tag)
|
||||
@@ -200,8 +173,7 @@ mailbox_respond(
|
||||
if (!reply.valid())
|
||||
return j6_err_invalid_arg;
|
||||
|
||||
j6_status_t s = prep_send(reply.msg, tag, 0,
|
||||
data, data_len,
|
||||
j6_status_t s = prep_send(reply.msg, tag, subtag,
|
||||
handles, handle_count);
|
||||
|
||||
if (s != j6_status_ok) {
|
||||
@@ -216,22 +188,19 @@ mailbox_respond(
|
||||
j6_status_t
|
||||
mailbox_respond_receive(
|
||||
mailbox *self,
|
||||
uint64_t * tag,
|
||||
void * data,
|
||||
size_t * data_len,
|
||||
size_t data_in,
|
||||
j6_handle_t * handles,
|
||||
size_t * handle_count,
|
||||
uint64_t *tag,
|
||||
uint64_t *subtag,
|
||||
j6_handle_t *handles,
|
||||
size_t *handle_count,
|
||||
size_t handles_in,
|
||||
uint16_t * reply_tag,
|
||||
uint64_t * badge,
|
||||
uint16_t *reply_tag,
|
||||
uint64_t flags)
|
||||
{
|
||||
j6_status_t s = mailbox_respond(self, *tag, data, data_in, handles, handles_in, *reply_tag);
|
||||
j6_status_t s = mailbox_respond(self, *tag, *subtag, handles, handles_in, *reply_tag);
|
||||
if (s != j6_status_ok)
|
||||
return s;
|
||||
|
||||
s = mailbox_receive(self, tag, data, data_len, handles, handle_count, reply_tag, badge, flags);
|
||||
s = mailbox_receive(self, tag, subtag, handles, handle_count, reply_tag, flags);
|
||||
if (s != j6_status_ok)
|
||||
return s;
|
||||
|
||||
|
||||
@@ -41,12 +41,9 @@ process_exit(int32_t status)
|
||||
}
|
||||
|
||||
j6_status_t
|
||||
process_give_handle(process *self, handle *target, j6_handle_t *received)
|
||||
process_give_handle(process *self, j6_handle_t target)
|
||||
{
|
||||
j6_handle_t out = self->add_handle(target->object, target->caps());
|
||||
if (received)
|
||||
*received = out;
|
||||
|
||||
self->add_handle(target);
|
||||
return j6_status_ok;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user