Liste des Groupes | Revenir à c arch |
MitchAlsup1 <mitchalsup@aol.com> wrote:The RAM on my FPGA boards only provides a 16-bit bus interface.BGB wrote:If you have ECC RAM on your FPGA board you could use the ECC bits for tags.
>On 3/9/2024 1:58 PM, Robert Finch wrote:<snip>On 2024-03-09 1:56 p.m., BGB wrote:On 3/9/2024 9:09 AM, Scott Lurndal wrote:mitchalsup@aol.com (MitchAlsup1) writes:>>
For Femtiki OS, I have a single object describing an array of values.
For instance messages which are small objects, are described with a
single object for an array of messages. It is too costly to use an
object descriptor for each message.For a CHERI like approach, one would need a tag of 1 bit for every 16>
bytes of RAM (to flag whether or not that RAM represents a valid
capability).For the combination of RAM sizes and FPGAs I have access to, this is
non-viable, as I would need more BRAM for the tag memory than exists in
the FPGAs.
Otherwise a tag cache is another way. The L1s and L2s carry tags (ie 129
bit datapath), but you just put the tag cache on the front of your DRAM.
Yeah. In any case, tag bits need to be somewhere where the page-swapping code has access to them...Yes, indeed, not viable. Now imagine a page of those, and now you haveOur swapping implementation keeps the tag bits in RAM, while the page is
to write out 4096 bytes and 2048-tag-bits onto a disk with standard
sectors......
swapped out. Eventually you need to swap out a page of tag bits, but that's
much less common.
The model of C that I consider normal arguably has a fair bit of UB.The C experience is fairly normal, as long as you are actually playing byIn effect, this will mean needing another smaller cache which is bolted>
onto the L2 cache or similar, whose sole purpose is to provide tag-bits
(and probably bounce requests to some other area of RAM which contains
the tag-bits memory).
Denelcor HEP had tag-like-bits and all the crud they bring (but they were
used as locks instead of tags).
>>>I think this may not be necessary, but I have to read some more. The
As I see it, "locking things down" would likely require turning things
like "malloc()/free()", "dlopen()/dlsym()/...", etc, into system calls
(and generally giving the kernel a much more active role in this
process).
>
capabilities have transfer rules which might make it possible to use
existing code. They have ported things over to Riscv. It cannot be too
mountainous a task.
>You can make it work, yes, but the question is less "can you make it
work, technically", but more:
Can you make it work in a way that provides both a fairly normal C
experience, and *also* an unbreakable sandbox, at the same time.
the C rules. You can't arbitraily cast integers to pointers - if you plan
to do that you need to use intptr_t so the compiler knows to keep the data
in a capability so it can use it as a pointer later.
Tricks which store data in the upper or lower bits of pointers are awkward.
Other tricks like XOR linked lists of pointers don't work. This is all
stuff that's pushing into the 'undefined behaviour' parts of C (even if C
doesn't explicitly call it out).
Changes in a 6M LoC KDE desktop codebase were 0.026% of lines:Seems so.
https://www.capabilitieslimited.co.uk/_files/ugd/f4d681_e0f23245dace466297f20a0dbd22d371.pdf
Depends what you mean by 'unbreakable sandbox': this is compiling code with
every pointer being a capability, so every memory access is bounds checked.
Sandboxing involves dividing code into compartments; that involves some
decision making as to where you draw the security boundaries. There aren't
good tools to do that (they are being worked on). CHERI offers you the
tools to implement whatever compartmentalisation stategy you wish, but it's
not quite as simple as just recompiling.
It stops you from crafting pointers directly...And here the answer is essentially <wait for it> no.Why would you want to ASLR? ASLR is to prevent you guessing valid addresses
>My skepticism here is that, short of drastic measures like moving malloc>
and libdl and similar into kernel space, it may not be possible to keep
the sandbox secure using solely capabilities.ASLR could help, but using ASLR to maintain an image of integrity for>
the capability system would be "kinda weak".
How do you ALSR code when a latent capability on disk still points at
its defined memory area ? Yes, you can ALSR at boot, but you can use
the file system to hold capabilities {which is something most capability
systems desire and promote.}
for things so you can't craft pointers to them. CHERI prevents you crafting
pointers to arbitrary things in the first place.
It is a question of what can be done without compromising security.That's the microkernel setup: the software running in system mode holdsOne could ask though:>
How is my security model (with Keyrings) any different?Well, the partial answer mostly is that a call that switches keyrings is>
effectively accomplished via context switches (with the two keyrings
effectively running in separate threads).So, like, even if the untrusted thread has a pointer to the protected>
thread's memory, it can't access it...Though, a similar model could potentially be accomplished with>
conventional page-tables, by making pseudo-processes which only share
parts of their address space with another process (and the protected
memory is located in the non-shared spaces, with any calls between them
via an RPC mechanism).
Capability manipulation via messages.
the privilege to alter access control (via page tables), so any time you
want to change that you have to ask the system (microkernel or whatever) to do
so. That's slow, in particular TLB manipulation (invalidation and
shootdowns). CHERI allows you to manipulate them in userspace without
having to call out to the kernel. Additionally it is finer grained than page
granularity.
Some experimental OSes have done things with manipulating page tables from
userspace processes which avoids syscall overhead but not TLB costs - and it
probably depends on the architecture whether you can do TLB invalidations
from userspace.
Yeah.A lot of modern software is well behaved (see figure above). ParticularHad considered mechanisms which could pull this off without a context>
switch, but most would fall short of "acceptably secure" (if a path
exists where a task could modify its own KRR or similar, this mechanism
is blown).
>My bounds-checking scheme also worked, but with a caveat:>
It only works if code does not get "overly clever" with the use of pointers.
Which no-one can trust of C programs.
software like JIT compilers can be more awkward - ideally you would really want
the JIT compiler to emit capability-aware code. You can still run generated
aarch64/rv64 non-capability code, but without the benefit of capability
checks.
A lot of the code I am dealing with has similar sorts of issues.That's the kind of thing that fall down: software being 'clever', where itSo, it worked well enough to where I was able to enable full
bounds-checking in Doom and similar, but was not entirely transparent to
some of the runtime code. If you cast between pointers and integers, and
manipulate the pointer bits, there are "gotchas".
doesn't need to be. I get the sense Doom's primary purpose in life was
being 'clever' in order to be fast on a 386.
Possibly, but only if one can trust that the code is compiled with a safe/trusted compiler of that language; or security enforcement via a VM (like in the JVM or .NET).Gee, if only we had trained programmers to avoid some of the things weIf only we could rewrite all the software out there in memory-safe
are now requiring new languages to prevent.....
languages... then we'd have twice as much software (and more bugs).
I was thinking, say, of one built on the NaN boxing approach or similar.We've had the DukTape Javascript interpreter working for CHERI for a while.Either pointer<->integer casting would need to be disallowed, or (more>
likely), turned into a runtime call which can "bless" the address before
returning it as a capability, which would exist as another potential
attack surface (unless, of course, this mechanism is itself turned into
a system call).
>OTOH:>
If one can't implement something like a conventional JavaScript VM, or
if it takes a significant performance hit, this would not be ideal.
Going for 2 in one post !!
Work is under way to port Chromium and V8 - that's a much bigger project,
just because Chromium is a huge piece of software (and we're running on
FreeBSD, which is not a platform that Chrome supports building for). The
work in V8 is to get it to implement the JS object model using CHERI
instructions as part of its generated code.
OK.We originally started out with a 256-bit capability with explicit base andThough, on my side of things, it is possible I could revive a modifiedYeah, IMO explicit upper and lower bounds would be better even though it
form of the 128-bit ABI, while dropping the VAS back down to 48 bits,
and turn it into a more CHERI-like form (with explicit upper and lower
bounds and access-enable flags, rather than a shared-exponent size and
bias scheme).
>
uses more memory. The whole manipulation of the bounds is complex. I
sketched out using a 256b capability descriptor. Some of the bits can be
trimmed from the bounds if things are page aligned.
top - this was to try things out simply so as not to prematurely optimise.
One early finding was that we needed to support capabilities being out of
bounds, as long as they aren't dereferenced out of bounds - software
sometimes saves a pointer that's before or after the object, before then
bringing it back in bounds when dereferencing it.
This is something the 128-bit compressed capability format supports, which
compresses the bounds a bit like floating point. This imposes certain
limits on bounds granularity, but they haven't been a problem in practice -
memory allocators tend to allocate objects in aligned chunks anyway (eg ask
for a 128MiB block and it'll probably be page aligned). The pointer is always
byte aligned.
Theo
Les messages affichés proviennent d'usenet.