[kernel] Add capabilities to handles

This change finally adds capabilities to handles. Included changes:

- j6_handle_t is now again 64 bits, with the highest 8 bits being a type
  code, and the next highest 24 bits being the capability mask, so that
  programs can check type/caps without calling the kernel.
- The definitions grammar now includes a `capabilities [ ]` section on
  objects, to list what capabilities are relevant.
- j6/caps.h is auto-generated from object capability lists
- init_libj6 again sets __handle_self and __handle_sys, this is a bit
  of a hack.
- A new syscall, j6_handle_list, will return the list of existing
  handles owned by the calling process.
- syscall_verify.cpp.cog now actually checks that the needed
  capabilities exist on handles before allowing the call.
This commit is contained in:
Justin C. Miller
2022-01-28 01:49:26 -08:00
parent 9b75acf0b5
commit f1246f84e0
38 changed files with 290 additions and 177 deletions

View File

@@ -9,34 +9,40 @@ namespace obj {
struct handle
{
inline handle(j6_handle_t in_id, kobject *in_object, j6_cap_t in_caps) :
id {in_id}, object {in_object}, caps {in_caps} {
// A j6_handle_t is an id in the low 32 bits, caps in bits 32-55, and type in 56-63
static inline j6_handle_t make_id(j6_handle_t id, j6_cap_t caps, kobject *obj) {
return (id & 0xffffffffull) |
static_cast<j6_handle_t>(caps) << 32 |
static_cast<j6_handle_t>(obj ? obj->get_type() : kobject::type::none) << 56;
}
inline handle(j6_handle_t in_id, kobject *in_obj, j6_cap_t caps) :
id {make_id(in_id, caps, in_obj)}, object {in_obj} {
if (object) object->handle_retain();
}
inline handle(const handle &other) :
id {other.id}, object {other.object}, caps {other.caps} {
id {other.id}, object {other.object} {
if (object) object->handle_retain();
}
inline handle(handle &&other) :
id {other.id}, object {other.object}, caps {other.caps} {
id {other.id}, object {other.object} {
other.id = 0;
other.caps = 0;
other.object = nullptr;
}
inline handle & operator=(const handle &other) {
if (object) object->handle_release();
id = other.id; caps = other.caps; object = other.object;
id = other.id; object = other.object;
if (object) object->handle_retain();
return *this;
}
inline handle & operator=(handle &&other) {
if (object) object->handle_release();
id = other.id; caps = other.caps; object = other.object;
other.id = other.caps = 0; other.object = nullptr;
id = other.id; object = other.object;
other.id = 0; other.object = nullptr;
return *this;
}
@@ -44,12 +50,14 @@ struct handle
if (object) object->handle_release();
}
inline j6_cap_t caps() const { return id >> 32; }
inline bool has_cap(j6_cap_t test) const {
return (caps & test) == test;
return (caps() & test) == test;
}
inline kobject::type type() const {
return object->get_type();
return static_cast<kobject::type>(id >> 56);
}
inline int compare(const handle &o) {
@@ -75,7 +83,6 @@ struct handle
inline const kobject * as<kobject>() const { return object; }
j6_handle_t id;
j6_cap_t caps;
kobject *object;
};