[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

@@ -0,0 +1,25 @@
#pragma once
// vim: ft=cpp
/// \file caps.h
/// Capability bitfield constants
/*[[[cog code generation
from definitions.context import Context
ctx = Context(definitions_path)
ctx.parse("syscalls.def")
syscalls = ctx.interfaces["syscalls"]
for obj in syscalls.exposes:
i = 0
for cap in obj.object.caps:
name = f"j6_cap_{obj.object.name}_{cap}"
cog.outl(f"#define {name:<30} (1 << {i})")
i += 1
name = f"j6_cap_{obj.object.name}_all"
cog.outl(f"#define {name:<30} ((1<<{i})-1)")
cog.outl()
]]]*/
/// [[[end]]]

View File

@@ -18,4 +18,5 @@
#define j6_err_not_ready j6_err(0x0004)
#define j6_err_insufficient j6_err(0x0005)
#define j6_err_timed_out j6_err(0x0006)
#define j6_err_denied j6_err(0x0007)

View File

@@ -27,14 +27,16 @@ typedef uint64_t j6_tag_t;
#define j6_tag_from_irq(x) ((x) | j6_tag_irq_base)
#define j6_tag_to_irq(x) ((x) & ~j6_tag_irq_base)
/// Handles are references and capabilities to other objects.
typedef uint32_t j6_handle_t;
/// Handles are references and capabilities to other objects. A handle is
/// an id in the lower 32 bits, a bitfield of capabilities in bits 32-55
/// and a type id in bits 56-63.
typedef uint64_t j6_handle_t;
/// Bitfield for storage of capabilities on their own
typedef uint32_t j6_cap_t;
#define j6_handle_invalid ((j6_handle_t)-1)
/// Bitfield for storage of capabilities
typedef uint32_t j6_cap_t;
enum j6_object_type {
#define OBJECT_TYPE( name, val ) j6_object_type_ ## name = val,
#include <j6/tables/object_types.inc>

View File

@@ -3,45 +3,47 @@
#ifndef __j6kernel
#include <stdint.h>
#include <j6/errors.h>
#include <j6/init.h>
#include <j6/syscalls.h>
#include <j6/types.h>
static size_t __initc = 0;
static struct j6_init_value *__initv = 0;
j6_handle_t __handle_sys = j6_handle_invalid;
j6_handle_t __handle_self = j6_handle_invalid;
extern "C" void
_get_init(size_t *initc, struct j6_init_value **initv)
{
if (!initc)
return;
namespace {
constexpr size_t __static_arr_size = 4;
j6_handle_t __handle_array[__static_arr_size];
*initc = __initc;
if (initv)
*initv = __initv;
}
static j6_status_t
__load_handles()
{
size_t count = __static_arr_size;
j6_handle_t *handles = __handle_array;
j6_status_t s = j6_handle_list(handles, &count);
if (s != j6_err_insufficient && s != j6_status_ok)
return s;
if (count > __static_arr_size)
count = __static_arr_size;
for (size_t i = 0; i < count; ++i) {
uint8_t type = (handles[i] >> 56);
if (type == j6_object_type_system && __handle_sys == j6_handle_invalid)
__handle_sys = handles[i];
else if (type == j6_object_type_process && __handle_self == j6_handle_invalid)
__handle_self = handles[i];
}
return s;
}
} // namespace
extern "C" void
_init_libj6(uint64_t *rsp)
{
uint64_t argc = *rsp++;
rsp += argc;
__initc = *rsp++;
__initv = (struct j6_init_value *)rsp;
for (unsigned i = 0; i < __initc; ++i) {
if (__initv[i].type == j6_init_handle_other &&
__initv[i].handle.type == j6_object_type_system) {
__handle_sys = __initv[i].handle.handle;
}
else if (__initv[i].type == j6_init_handle_self &&
__initv[i].handle.type == j6_object_type_process) {
__handle_self = __initv[i].handle.handle;
}
}
__load_handles();
}
#endif // __j6kernel

View File

@@ -5,6 +5,7 @@ j6 = module("j6",
includes = [ "include" ],
sources = [
"init.cpp",
"include/j6/caps.h.cog",
"include/j6/syscalls.h.cog",
"include/j6/sysconf.h.cog",
"syscalls.s.cog",
@@ -18,6 +19,7 @@ sysconf = join(source_root, "definitions/sysconf.yaml")
definitions = glob('definitions/**/*.def', recursive=True)
j6.add_depends([
"include/j6/caps.h.cog",
"include/j6/syscalls.h.cog",
"syscalls.s.cog",
], definitions)

View File

@@ -3,7 +3,7 @@
#include <j6/syscalls.h>
//void *sbrk(intptr_t) __attribute__ ((weak));
static j6_handle_t __core_handle = 0;
static j6_handle_t __core_handle = j6_handle_invalid;
static intptr_t __core_size = 0;
static const uintptr_t __core_base = 0x1c0000000;