[kernel] Add automatic verification to syscalls

Since we have a DSL for specifying syscalls, we can create a verificaton
method for each syscall that can cover most argument (and eventually
capability) verification instead of doing it piecemeal in each syscall
implementation, which can be more error-prone.

Now a new _syscall_verify_* function exists for every syscall, which
calls the real implementation. The syscall table for the syscall handler
now maps to these verify functions.

Other changes:

- Updated the definition grammar to allow options to have a "key:value"
  style, to eventually support capabilities.
- Added an "optional" option for parameters that says a syscall will
  accept a null value.
- Some bonnibel fixes, as definition file changes weren't always
  properly causing updates in the build dep graph.
- The syscall implementation function signatures are no longer exposed
  in syscall.h. Also, the unused syscall enum has been removed.
This commit is contained in:
Justin C. Miller
2022-01-16 15:11:58 -08:00
parent e845379b1e
commit e0246df26b
21 changed files with 415 additions and 219 deletions

View File

@@ -34,6 +34,7 @@ class Context:
pending = set()
pending.add(filename)
from .parser import LarkError
from .parser import Lark_StandAlone as Parser
from .transformer import DefTransformer
@@ -47,7 +48,16 @@ class Context:
path = self.find(name)
parser = Parser(transformer=DefTransformer(name))
imps, objs, ints = parser.parse(open(path, "r").read())
try:
imps, objs, ints = parser.parse(open(path, "r").read())
except LarkError as e:
import sys
import textwrap
print(f"\nError parsing {name}:", file=sys.stderr)
print(textwrap.indent(str(e), " "), file=sys.stderr)
sys.exit(1)
objects.update(objs)
interfaces.update(ints)

File diff suppressed because one or more lines are too long

View File

@@ -5,10 +5,15 @@ def _indent(x):
class Description(str): pass
class Import(str): pass
class Options(set):
class Options(dict):
def __init__(self, opts = tuple()):
for opt in opts:
parts = opt.split(":", 1)
self[parts[0]] = "".join(parts[1:])
def __str__(self):
if not self: return ""
return "[{}]".format(" ".join(self))
return "[{}]".format(" ".join(self.keys()))
class UID(int):
def __str__(self):

View File

@@ -47,3 +47,15 @@ class Param:
return "param {} {} {} {}".format(
self.name, repr(self.type), self.options, self.desc or "")
@property
def outparam(self):
return "out" in self.options or "inout" in self.options
@property
def refparam(self):
return self.type.reference or self.outparam
@property
def optional(self):
return "optional" in self.options

View File

@@ -8,9 +8,9 @@ class Primitive(Type):
def __repr__(self):
return f'Primitive({self.name})'
def c_names(self, options=None):
def c_names(self, options=dict()):
one = self.c_type
if options and "out" in options or "inout" in options:
if "out" in options or "inout" in options:
one += " *"
return ((one, ""),)
@@ -23,11 +23,13 @@ class PrimitiveRef(Primitive):
super().__init__(name, c_type)
self.__counted = counted
def c_names(self, options=None):
reference = property(lambda self: True)
def c_names(self, options=dict()):
one = f"{self.c_type} *"
two = "size_t"
if options and "out" in options or "inout" in options:
if "out" in options or "inout" in options:
two += " *"
else:
one = "const " + one

View File

@@ -3,6 +3,7 @@ class Type:
self.__name = name
name = property(lambda self: self.__name)
reference = property(lambda self: False)
def c_names(self, options):
raise NotImplemented("Call to base Type.c_names")