NotBoolean 3 days ago

Always interesting to see new RTOSs. However, I’m not sure CHERIoT is, I read the about section I’m still not too sure. Can anyone give me a ELI5?

  • crest 3 days ago

    CHERI is a redesign of how an ISA accesses memory to protect against memory corruption under the assumption that it's easier to extend an instruction set and recompile existing C and C++ code (with minimal changes) than rewrite every existing C program and library in the latest safe language.

    It works by changing pointers from (in assembler) equivalent to integers to a hardware supported capability type. That type is twice the size of an address contains the bounds on the memory allocation it points into. Each such double capability is also protected against manipulation by an extra bit that isn't addressable by normal means (to record the manipulation invalidating the capability).

    At first glance having twice as fat pointers should slow things down, but if you fully commit to the hardware capabilities in your OS you can get away with a minimal MMU could more than make up the overhead of larger pointers (faster context switches, less TLB stalls, etc.)

  • magicalhippo 3 days ago

    CHERI is an instruction set extension[1], which is aimed at increasing security:

    The CHERI memory-protection features allow historically memory-unsafe programming languages such as C and C++ to be adapted to provide strong, compatible, and efficient protection against many currently widely exploited vulnerabilities.

    These features enable new software constructs that are incrementally deployable within existing software ecosystems.

    So while it's possible to add CHERI to existing projects, to get the full benefits they decided they needed to go all-in, hence CHERIoT.

    [1]: https://www.cl.cam.ac.uk/research/security/ctsrd/cheri/

    • wahern 3 days ago

      And one of the unique things the CHERI-based architecture permits is a single, flat, shared address space:

      > CHERIoT was designed to provide both spatial and temporal safety, both enforced efficiently in the hardware. As such, we can rely on a shared heap, even in situations where you need to provide mutual distrust.

      This means you can pass pointers directly between processes. A pointer isn't just an address, it's a capability, similar to a file descriptor in that you cannot forge one.

      This means there's no need for virtual address space mappings, which could in theory provide some significant performance gains, similar to unikernels but without sacrificing hardware-enforced memory protections. Though, capability pointers have their own costs--in memory, in the need to garbage collect old pointers--so it remains to be seen what the net cost would be in a system fully optimized for these abilities.

      • wzdd 2 days ago

        > one of the unique things the CHERI-based architecture permits is a single, flat, shared address space

        Although a hardware-optimised take on this is interesting, CHERI is not unique in allowing a flat, shared-address-space operating system using hardware-enforced memory protection.

        You can imagine doing such a thing on a regular system by associating a set of capabilities with each thread or process. The capabilities refer to a range of the single address space. Normally the range is not mapped to that process; when the process tries to access the range the kernel handles the page fault by checking the capability list and mapping the range. If a capability is revoked the range is unmapped again and associated caches (i.e. the TLB) are flushed.

        This scheme obviously has different trade-offs versus using hardware-checked fat pointers, but has the advantage that it can be implemented on commodity hardware.

        This is the basic idea behind the Mungi single-address-space operating system from 1998, among others. (https://research.ibm.com/publications/the-mungi-single-addre...). Is it also straightforward to implement such a scheme at user level in some implementations of L4.

      • Veserv 3 days ago

        Handling fragmentation is likely the bigger problem. There are some questions about revokation, demand paging, and probably some other things that I am forgetting, but most of those have potential, non-intrusive solutions.

        However I have not seen anything that effectively handles fragmentation. Maybe you could do some sort of transparent compaction in conjunction with “demand paging” in the relocated area, but that would be very intrusive and likely only provide runtime guarantees like a system using a compacting GC.

        • nullc 3 days ago

          > There are some questions about revokation,

          I'm not sure what you mean by questions. But cheri does have an answer to how revocation works: All cheri capabilities (pointers) are tagged and the tags are controlled with protected instructions. To revoke a capability, you can sweep the tagged memory and untag any revoked cabability. To reduce revocation work, you can defer reusing cabilities for as long as reasonable and then revoke many in a single sweep.

          Of course, this is not cheap compared to the rest of cheri-- but they do have an answer to it, and it's implemented e.g. in cheribsd. It's intrusive (at least in terms of performance/latency) as you note, though it's distinct from most other GC approaches because it's secure even against malicious code, and can't have false positives or false negatives (because tags are completely unambigious).

          One of the cool things about cheri is that it eliminates the need for a TLB for security reasons which could have positive performance effects... unfortunately virtual memory is still needed for virtual memory that exceeded physical memory. Though for an IOT-ish device swap is probably a non-issue.

          • Veserv 3 days ago

            Revokation that demands a full memory sweep is problematic in high security use cases, but potentially workable.

            Which is my point about questions; there exists a potential solution but it remains to be seen how effective it would be in the circumstances.

            Personally, I think they should probably implement a two-level capability. The kernel presents a top-level capability during allocation requests which userspace can then derive from at will. Kernel revokation of the top-level capability would revoke any derived capability. The derivation relation can almost certainly be stored in the tag resulting in no additional space requirements per-capability. At worst you could add some additional hardware machinery to support efficiently managing and resolving the derivation relation.

            But again, potential solutions with some questions around usability.

      • nummer10 3 days ago

        Would this allow for AmigaOS style message passing with memory protection?

  • steveklabnik 3 days ago

    CHERI: https://www.cl.cam.ac.uk/research/security/ctsrd/cheri/

    > CHERI extends conventional hardware Instruction-Set Architectures (ISAs) with new architectural features to enable fine-grained memory protection and highly scalable software compartmentalization. The CHERI memory-protection features allow historically memory-unsafe programming languages such as C and C++ to be adapted to provide strong, compatible, and efficient protection against many currently widely exploited vulnerabilities.

    CHERIoT is work towards bringing similar things to RISC-V for IoT use-cases.

bfrog 2 days ago

Or… you could use a memory safe language and not have to try and patch up things in hardware for buggy software.

If we didn’t have Rust this would be super cool. With Rust this seems like slapping flexseal on the leaky boat.