[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:
@@ -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
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user