-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
One-way address exposure for FFI #11
Comments
Conceptually, the kernel uses
If the arguments are |
True, but there were 2 reasons that made me hesitate:
With formatting I meant "laying out in memory". Yeah, |
Basically, yes. If you are smuggling pointers through integer types, you are not following strict provenance. There is no way around that; an alternative kind of exposure operation would also be outside of strict provenance. Now, the strict provenance experiment also lead to a better understanding of "permissive provenance", using
You intend the kernel to use
Don't get me wrong, it would be nice to do some |
[...]
I skimmed through these, but I have to admit I did not read them fully. Thanks for the hints! I think #95496 does indeed apply, even though I think it does not fully describe the huge scope of kernel APIs that do this. Once you start looking at driver APIs (graphics, input, sound, ...) everything is pointers stashed into u64.
Na, I meant it can assume it is never called from my context. So if it merely tracks my address space, it can assume it is exposed, but avoid putting it in lookup-trees, because no
I will have a look into a u64+ptr union that works even on big-endian+32bit-compat. I am still unsure how to stash this into 32bit syscall wrappers, which split u64 across arguments, but maybe I push this into the inline-asm and be fine with it. I will close this issue. Thanks a lot for the detailed responses! I might just comment on #95496 eventually with a summary, so you guys can better track crates that require |
Not sure which lookup-trees you mean -- the "set of exposed pointers" that the semantics tracks is entirely conceptual, it does not exist at runtime. It does affect compiler analyses, but it is crucial that those analyses do track that your pointer is exposed since otherwise, again, the compiler could assume that the kernel does not read or write that memory. The fact that the |
Hi!
I am maintaining rust code that provides direct access to the linux syscalls. In a lot of scenarios the linux kernel uses
u64
for pointers to make sure 32bit/64bit mixed systems have a single ABI (kernel calls workarounds for it 'compat'-mode). In other scenarios,unsigned long
oru64
basically contain unions of lots of different argument options. If I understood correctly, there is no inherent conflict with strict provenance, though I struggle to properly implement it.I understand that the recommendation is to make FFI calls take a pointer-type as argument, even if the other side takes an
unsigned long
(or similar). However, what if the full set of possible arguments is either too big or unknown? In my case, I havesyscall0()
up tosyscall6()
which corresponds to the libcsyscall(...)
function. They are implemented in rust with inline assembly and simply take 0 to 6usize
arguments. No external linkage required at all. On top, I have typed per-syscall wrappers. But under strict provenance, I cannot implement the typed-wrappers but have to resort toexpose_addr()
, even though I never usefrom_exposed_addr()
. I want to avoid implementing the syscall stubs in C or other FFI. This is pure rust (minus inline assembly).My ideal solution would be a way to take a pointer in rust and format it as an integer of my choice. I am fine with it still being a pointer, but I want it to be formatted like a
u64
(or another integer of my choice bigger thanusize
, depending on platform). I can then pass it to the syscall and be done with it. Alternatively, there must be some state-change that miri/etc. apply to a pointer passed through FFI, and I would be fine calling the same function on that pointer. Something likepublish_addr()
that tells miri/etc. to assume the address was exposed via FFI.Note that formatting the value as union does not work here. For instance, assume a big-endian 32bit architecture with a 64bit syscall argument. The union would look like this:
Assigning a pointer to
Arg.ptr
would differ from assigning its address toArg.int
, since on big-endian the 32bitArg.ptr
would be aligned to the start of the union, while inArg.int
the lower 32bits would be at the end of the union (I could useptrs: [*mut core::ffi::c_void; 2]
and store in the right bucket, but not sure that is the right solution?).So I am a bit out of ideas what to do and looking for help!
Thanks
David
The text was updated successfully, but these errors were encountered: