Date: Sun, 8 Sep 2024 09:53:57 +0100 From: David Chisnall <theraven@freebsd.org> To: Paul Floyd <paulf2718@gmail.com> Cc: freebsd-hackers@freebsd.org Subject: CHERIoT RTOS C++ [Re: The Case for Rust (in any system)] Message-ID: <D42EC8C5-9100-4209-AB49-091FCE48F8B2@freebsd.org> In-Reply-To: <5d707cd5-ee31-4cce-98b7-3826e891a2dd@gmail.com> References: <5d707cd5-ee31-4cce-98b7-3826e891a2dd@gmail.com>
next in thread | previous in thread | raw e-mail | index | archive | help
--Apple-Mail-A0EC2FF2-7F8A-4D21-A958-19E93388C397 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Changing the title so people who don=E2=80=99t care can easily ignore this t= angent. > On 7 Sep 2024, at 20:20, Paul Floyd <paulf2718@gmail.com> wrote: >=20 > Out of curiosity, did that mean limiting the ABI use (no RTTI or exception= s). Did it also allow using different compilers (say clang and GCC)? We=E2=80=99re targeting tiny embedded systems. The total code size for the c= ore RTOS (scheduler, memory allocator, switcher) is around 10 KiB, so except= ions are totally infeasible. A stack unwinded would be as big as the total a= mount of RAM on some of the SoCs we want to be able to support. We also don=E2= =80=99t use RTTI for a similar reason. We do have a tiny C++ runtime for laz= y static initialisation. I wish the C++ standard would lose its allergy to subsetting, because the st= andard not subsetting does not prevent it happening, it just means everyone d= oes it differently. In terms of library support, we claim to be a freestandi= ng implementation and also provide a bunch of things from hosted implementat= ions. A lot of the normal standard library types are not well suited to envi= ronments where memory allocation can fail and where exceptions don=E2=80=99t= work (the libc++ code calls abort in these cases, we want things that retur= n std::optional for things that might fail). We are co-designing the hardware and software. We have some FPGA prototyping= platforms (lowRISC has built a really nice one) and the company I cofounded= will ship commercial silicon next year. We have some extensions beyond CHER= I that enable deterministic heap temporal safety as well. As soon as you fre= e an object, all pointers to it become unusable (and then we have some addit= ional hardware that makes it possible to safely reuse the memory).=20 So it=E2=80=99s not quite normal C++. We can inspect a pointer and tell what= its bounds are, what its permissions are, and whether it=E2=80=99s valid. W= e can also transform it into a tamper-proof =E2=80=98sealed=E2=80=99 pointer= that can be unsealed only if you hold the relevant unsealing token. This ca= n protect things like socket handles: the TCP/IP stack hands out a sealed po= inter to the socket state and can check when you pass it back that it is the= correct type and can then unseal it, but you everything else that pointer i= s a value that can be copied around but can=E2=80=99t be used. We can do som= e fun things (it=E2=80=99s possible to represent all of the state of a std::= vector with a single pointer, for example) and, in some places, we skip stat= ic memory safety checks and instead write code that expects to fail and retu= rn to the calling compartment if it encounters a memory-safety bug. This set of primitives lets us build a rich compartmentalisation model where= communication between compartments looks like a function call and sharing m= emory is accomplished by passing pointers (which may have restricted permiss= ions, including shallow or deep immutability and no-capture guarantees). On t= op of this, we have built auditing tooling that lets you see which compartme= nts call which entry points in others, which compartments have access to whi= ch MMIO regions, and so on. Our ABI defines a bunch of things that are extensions to the Itanium ABI suc= h as calling conventions for cross-compartment calls, shared libraries (whic= h, for us, are stateless and don=E2=80=99t involve a security domain crossin= g, whereas compartments do). We don=E2=80=99t have support for more than one compiler at the moment becau= se our extensions are implemented only in clang. There is nothing stopping a= nyone adding the same support in other compilers though and I=E2=80=99d be h= appy to help anyone who wanted to do gcc bring up. More details (code, formal model of the ISA, programmers=E2=80=99 handbook, a= nd so on here): https://cheriot.org/ David --Apple-Mail-A0EC2FF2-7F8A-4D21-A958-19E93388C397 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable <html><head><meta http-equiv=3D"content-type" content=3D"text/html; charset=3D= utf-8"></head><body dir=3D"auto"><div dir=3D"ltr"></div><div dir=3D"ltr">Cha= nging the title so people who don=E2=80=99t care can easily ignore this tang= ent.</div><div dir=3D"ltr"><br><div dir=3D"ltr"></div><blockquote type=3D"ci= te">On 7 Sep 2024, at 20:20, Paul Floyd <paulf2718@gmail.com> wrote:<b= r><br></blockquote></div><blockquote type=3D"cite"><div dir=3D"ltr">Out of c= uriosity, did that mean limiting the ABI use (no RTTI or exceptions). Did it= also allow using different compilers (say clang and GCC)?</div></blockquote= ><br><div>We=E2=80=99re targeting tiny embedded systems. The total code size= for the core RTOS (scheduler, memory allocator, switcher) is around 10 KiB,= so exceptions are totally infeasible. A stack unwinded would be as big as t= he total amount of RAM on some of the SoCs we want to be able to support. We= also don=E2=80=99t use RTTI for a similar reason. We do have a tiny C++ run= time for lazy static initialisation.</div><div><br></div><div>I wish the C++= standard would lose its allergy to subsetting, because the standard not sub= setting does not prevent it happening, it just means everyone does it differ= ently. In terms of library support, we claim to be a freestanding implementa= tion and also provide a bunch of things from hosted implementations. A lot o= f the normal standard library types are not well suited to environments wher= e memory allocation can fail and where exceptions don=E2=80=99t work (the li= bc++ code calls abort in these cases, we want things that return std::option= al for things that might fail).</div><div><br></div><div>We are co-designing= the hardware and software. We have some FPGA prototyping platforms (lowRISC= has built a really nice one) and the company I cofounded will ship commerci= al silicon next year. We have some extensions beyond CHERI that enable deter= ministic heap temporal safety as well. As soon as you free an object, all po= inters to it become unusable (and then we have some additional hardware that= makes it possible to safely reuse the memory). </div><div><br></div><d= iv>So it=E2=80=99s not quite normal C++. We can inspect a pointer and tell w= hat its bounds are, what its permissions are, and whether it=E2=80=99s valid= . We can also transform it into a tamper-proof =E2=80=98sealed=E2=80=99 poin= ter that can be unsealed only if you hold the relevant unsealing token. This= can protect things like socket handles: the TCP/IP stack hands out a sealed= pointer to the socket state and can check when you pass it back that it is t= he correct type and can then unseal it, but you everything else that pointer= is a value that can be copied around but can=E2=80=99t be used. We can do s= ome fun things (it=E2=80=99s possible to represent all of the state of a std= ::vector with a single pointer, for example) and, in some places, we skip st= atic memory safety checks and instead write code that expects to fail and re= turn to the calling compartment if it encounters a memory-safety bug.</div><= div><br></div><div>This set of primitives lets us build a rich compartmental= isation model where communication between compartments looks like a function= call and sharing memory is accomplished by passing pointers (which may have= restricted permissions, including shallow or deep immutability and no-captu= re guarantees). On top of this, we have built auditing tooling that lets you= see which compartments call which entry points in others, which compartment= s have access to which MMIO regions, and so on.</div><div><br></div><div>Our= ABI defines a bunch of things that are extensions to the Itanium ABI such a= s calling conventions for cross-compartment calls, shared libraries (which, f= or us, are stateless and don=E2=80=99t involve a security domain crossing, w= hereas compartments do).</div><div><br></div><div>We don=E2=80=99t have supp= ort for more than one compiler at the moment because our extensions are impl= emented only in clang. There is nothing stopping anyone adding the same supp= ort in other compilers though and I=E2=80=99d be happy to help anyone who wa= nted to do gcc bring up.</div><div><br></div><div>More details (code, formal= model of the ISA, programmers=E2=80=99 handbook, and so on here):</div><div= ><br></div><div><a href=3D"https://cheriot.org/">https://cheriot.org/</a></d= iv><div><br></div><div>David</div><div><br></div></body></html>= --Apple-Mail-A0EC2FF2-7F8A-4D21-A958-19E93388C397--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?D42EC8C5-9100-4209-AB49-091FCE48F8B2>