Use dedicated types to statically check for write or exec MappedPages permissions
Expand the existing MappedPages type to have statically-typed permissions semantics:
MappedPagesis read-only.- It only offers the
as_type()andas_slice()functions.
- It only offers the
MappedPagesMutis an extension that is returned when the mapping is created with WRITABLE page table entry flags is set.- It adds the
as_type_mut()andas_slice_mut()functions.
- It adds the
MappedPagesExecis 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.
- It adds the
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(nowMappedPagesExec) objects used for.textsections - read-only
MappedPagesobjects used for.rodata,.gcc_except_table, and.eh_framesections - writable
MappedPages(nowMappedPagesMut) objects used for.dataand.bsssections
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.
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().