Theseus icon indicating copy to clipboard operation
Theseus copied to clipboard

Use dedicated types to statically check for write or exec MappedPages permissions

Open kevinaboos opened this issue 5 years ago • 1 comments

Expand the existing MappedPages type to have statically-typed permissions semantics:

  • MappedPages is read-only.
    • It only offers the as_type() and as_slice() functions.
  • MappedPagesMut is an extension that is returned when the mapping is created with WRITABLE page table entry flags is set.
    • It adds the as_type_mut() and as_slice_mut() functions.
  • MappedPagesExec is another extension that is returned when the mapping is created with the EXEC flag set, or rather when the NO_EXEC flag is not set (which is how it works on x86_64).
    • It adds the as_func() function.

Benefits

This will forbid creating a mapping that is both executable and writable, which is a good thing for security reasons.

This will also help disambiguate between different types of MappedPages* objects that are passed around the system; for example, it will distinguish between the following:

  • executable MappedPages (now MappedPagesExec) objects used for .text sections
  • read-only MappedPages objects used for .rodata, .gcc_except_table, and .eh_frame sections
  • writable MappedPages (now MappedPagesMut) objects used for .data and .bss sections

Finally, this has the obvious benefit of transforming runtime page table entry permissions mismatches into compile-time type mismatches. Currently, the existing singular MappedPages type

Note: this may also allow us to reduce the space occupied by a MappedPages* object by removing the flags field from the struct, but I'm not 100% confident that we can do that yet. I'd need to fully explore all use cases of the flags field in order to determine whether static multi-typing of MappedPages* objects will render the flags field obsolete.

kevinaboos avatar Apr 03 '20 18:04 kevinaboos

We can actually take this further: by leveraging const generics, we can create MappedPages* instances parameterized with a specific size (in bytes or pages), which is known at compile time. Then we can omit bounds and type size checks for those types when overlaying a struct atop it using as_type().

kevinaboos avatar Apr 24 '20 20:04 kevinaboos