5 ms·
Also this is _de facto_ limited to userspace application for the mainstream OSes if my understanding is correct. Reading Fil-C website's "InvisiCaps by exampl
by TuxSH 1y ago
Also this is _de facto_ limited to userspace application for the mainstream OSes if my understanding is correct.
Reading Fil-C website's "InvisiCaps by example" page, I see that "Laundering Integers As Pointers" is disallowed. This essentially disqualifies Fil-C for low-level work, which makes for a substantial part of C programs.
(int2ptr for MMIO/pre-allocated memory is in theory UB, in practice just fine as long as you don't otherwise break aliasing rules (and lifetime rules in C++) - as the compiler will fail to track provenance at least once).
But that isn't really what Fil-C is aimed at - the value is, as you implied, in hardening userspace applications.
- kragen 1y agoYes, I think that's reasonable. I imagine you wouldn't have to extend Fil-C very much to sneak some memory-mapped I/O addresses into your program, but maybe having the garbage collector pause the program in the middle of an interrupt handler would have other bad effects. Like, if you were generating a video signal, you'd surely get display glitches.
- mbrock 1y agoCheck out this document to see how the Fil-C ports of Python and Perl and so on work: https://github.com/mbrock/filnix/blob/main/ports/analysis.md https://github.com/mbrock/filnix/blob/main/ports/analysis.md This is still within the userspace application realm but it's good to know that Fil-C does have explicit capability-preserving operations (`zxorptr`, `zretagptr`, etc) to do e.g. pointer tagging, and special support for mapping pointers to integer table indices and back (`zptrtable`, etc).
- pizlonator 1y agoIt’s not so fundamental of a limitation. Fil-C already allows memory mapped I/O in the form of mmap. The only thing missing that is needed for kernel level MMIO is a way to forge a capability. I don’t allow that right now, but that’s mostly a policy decision. It also falls out from the fact that InvisiCaps optimize the lower by having it double as a pointer to the top of the capability. That’s also not fundamental; it’s an implementation choice. It’s true that InvisiCaps will always disallow int to ptr casts, in the sense that you get a pointer with no capability. You’d want MMIO code to have some intrinsic like `zunsafe_forge_ptr` that clearly calls out what’s happening and then you’d use that wherever you define your memory mapped registers.
- cyberax 1y agoI'm curious, what's your strategy for integrating the GC with low-level code? I've been thinking about trying to use it for Arduino development. Mostly as a thought experiment for now (as I'm playing with Rust on RP2040).
- pizlonator 1y agoIf it's userlevel code, then it just works. It's a concurrent GC. If I wanted to go to kernel, I'd probably get rid of the GC. I've tweeted about what Fil-C would look like without GC. Short version: use-after-free would not trap anymore, but you wouldn't be able to use it to break out of the capability system. Similar to CHERI without its capability GC.
- cyberax 1y agoArduino is kinda both. You have full control over the execution flow, but then you have to actually exercise the full control over the execution flow. The only major wrinkle are the hardware interrupts. One interesting feature is that there might be some synergy there. The GC safepoints can be used to implement cooperative multitasking, with capabilities making it safe.
- cryptonector 1y agoCan you "launder" pointers through integers just to do things like drop `const`? It's a very common pattern to have to drop attributes like `const` due to crappy APIs: `const foo a = ...; foo b = (foo *)(uintptr_t)a;`
- kragen 1y agoHopefully Pizlo will correct me if I get this wrong, but I don't think Fil-C's pointer tagging enforces constness, which isn't needed for C in any case. This C code compiles with no warnings and outputs "Howlong\n" with GCC 12.2.0-14 -ansi -pedantic -Wall -Wextra: #include <stdio.h> int main() { const char c[] = "Howling\n"; char *p = (char*)c; p[4] = 'o'; printf("%s", c); return 0; } Somewhat to my surprise, it still compiles successfully with no warnings as C++ (renaming to deconst.cc and compiling with g++). I don't know C++ that well, since I've only been using it for 35 years, which isn't nearly long enough to learn the whole language unless you write a compiler for it. Same results with Debian clang (and clang++) version 14.0.6 with the same options. Of course, if you change c[] to *c, it will segfault. But it still compiles successfully without warnings. Laundering your pointer through an integer is evidently not necessary.
- cv5005 11mo agoYou don't have to do int2ptr for mmio or absolute addresses, you can punt that to the linker. extern struct uart UART0; Then place that symbol at address X in your linker script.